2 Unix SMB/CIFS implementation.
3 basic raw test suite for oplocks
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "libcli/raw/libcliraw.h"
22 #include "libcli/raw/raw_proto.h"
23 #include "libcli/libcli.h"
24 #include "torture/util.h"
25 #include "lib/events/events.h"
26 #include "param/param.h"
27 #include "lib/cmdline/popt_common.h"
28 #include "libcli/resolve/resolve.h"
29 #include "torture/raw/proto.h"
31 #define CHECK_VAL(v, correct) do { \
32 if ((v) != (correct)) { \
33 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
34 __location__, #v, (int)v, (int)correct); \
38 #define CHECK_RANGE(v, min, max) do { \
39 if ((v) < (min) || (v) > (max)) { \
40 torture_warning(tctx, "(%s): wrong value for %s got " \
41 "%d - should be between %d and %d\n", \
42 __location__, #v, (int)v, (int)min, (int)max); \
45 #define CHECK_STRMATCH(v, correct) do { \
46 if (!v || strstr((v),(correct)) == NULL) { \
47 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got '%s' - should be '%s'\n", \
48 __location__, #v, v?v:"NULL", correct); \
53 #define CHECK_STATUS(tctx, status, correct) do { \
54 if (!NT_STATUS_EQUAL(status, correct)) { \
55 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
56 nt_errstr(status), nt_errstr(correct)); \
69 #define BASEDIR "\\test_oplock"
72 a handler function for oplock break requests. Ack it as a break to level II if possible
74 static bool oplock_handler_ack_to_given(struct smbcli_transport
*transport
,
75 uint16_t tid
, uint16_t fnum
,
76 uint8_t level
, void *private_data
)
78 struct smbcli_tree
*tree
= (struct smbcli_tree
*)private_data
;
81 break_info
.fnum
= fnum
;
82 break_info
.level
= level
;
86 case OPLOCK_BREAK_TO_LEVEL_II
:
89 case OPLOCK_BREAK_TO_NONE
:
94 break_info
.failures
++;
96 printf("Acking to %s [0x%02X] in oplock handler\n",
99 return smbcli_oplock_ack(tree
, fnum
, level
);
103 a handler function for oplock break requests. Ack it as a break to none
105 static bool oplock_handler_ack_to_none(struct smbcli_transport
*transport
,
106 uint16_t tid
, uint16_t fnum
,
107 uint8_t level
, void *private_data
)
109 struct smbcli_tree
*tree
= (struct smbcli_tree
*)private_data
;
110 break_info
.fnum
= fnum
;
111 break_info
.level
= level
;
114 printf("Acking to none in oplock handler\n");
116 return smbcli_oplock_ack(tree
, fnum
, OPLOCK_BREAK_TO_NONE
);
120 a handler function for oplock break requests. Let it timeout
122 static bool oplock_handler_timeout(struct smbcli_transport
*transport
,
123 uint16_t tid
, uint16_t fnum
,
124 uint8_t level
, void *private_data
)
126 break_info
.fnum
= fnum
;
127 break_info
.level
= level
;
130 printf("Let oplock break timeout\n");
134 static void oplock_handler_close_recv(struct smbcli_request
*req
)
137 status
= smbcli_request_simple_recv(req
);
138 if (!NT_STATUS_IS_OK(status
)) {
139 printf("close failed in oplock_handler_close\n");
140 break_info
.failures
++;
145 a handler function for oplock break requests - close the file
147 static bool oplock_handler_close(struct smbcli_transport
*transport
, uint16_t tid
,
148 uint16_t fnum
, uint8_t level
, void *private_data
)
151 struct smbcli_tree
*tree
= (struct smbcli_tree
*)private_data
;
152 struct smbcli_request
*req
;
154 break_info
.fnum
= fnum
;
155 break_info
.level
= level
;
158 io
.close
.level
= RAW_CLOSE_CLOSE
;
159 io
.close
.in
.file
.fnum
= fnum
;
160 io
.close
.in
.write_time
= 0;
161 req
= smb_raw_close_send(tree
, &io
);
163 printf("failed to send close in oplock_handler_close\n");
167 req
->async
.fn
= oplock_handler_close_recv
;
168 req
->async
.private_data
= NULL
;
173 static bool open_connection_no_level2_oplocks(struct torture_context
*tctx
,
174 struct smbcli_state
**c
)
177 struct smbcli_options options
;
178 struct smbcli_session_options session_options
;
180 lpcfg_smbcli_options(tctx
->lp_ctx
, &options
);
181 lpcfg_smbcli_session_options(tctx
->lp_ctx
, &session_options
);
183 options
.use_level2_oplocks
= false;
185 status
= smbcli_full_connection(tctx
, c
,
186 torture_setting_string(tctx
, "host", NULL
),
187 lpcfg_smb_ports(tctx
->lp_ctx
),
188 torture_setting_string(tctx
, "share", NULL
),
189 NULL
, lpcfg_socket_options(tctx
->lp_ctx
), cmdline_credentials
,
190 lpcfg_resolve_context(tctx
->lp_ctx
),
191 tctx
->ev
, &options
, &session_options
,
192 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
));
193 if (!NT_STATUS_IS_OK(status
)) {
194 torture_comment(tctx
, "Failed to open connection - %s\n",
203 Timer handler function notifies the registering function that time is up
205 static void timeout_cb(struct tevent_context
*ev
,
206 struct tevent_timer
*te
,
207 struct timeval current_time
,
210 bool *timesup
= (bool *)private_data
;
216 Wait a short period of time to receive a single oplock break request
218 static void torture_wait_for_oplock_break(struct torture_context
*tctx
)
220 TALLOC_CTX
*tmp_ctx
= talloc_new(NULL
);
221 struct tevent_timer
*te
= NULL
;
223 bool timesup
= false;
224 int old_count
= break_info
.count
;
226 /* Wait .1 seconds for an oplock break */
227 ne
= tevent_timeval_current_ofs(0, 100000);
229 if ((te
= tevent_add_timer(tctx
->ev
, tmp_ctx
, ne
, timeout_cb
, ×up
))
232 torture_comment(tctx
, "Failed to wait for an oplock break. "
233 "test results may not be accurate.");
237 while (!timesup
&& break_info
.count
< old_count
+ 1) {
238 if (tevent_loop_once(tctx
->ev
) != 0) {
239 torture_comment(tctx
, "Failed to wait for an oplock "
240 "break. test results may not be "
247 /* We don't know if the timed event fired and was freed, we received
248 * our oplock break, or some other event triggered the loop. Thus,
249 * we create a tmp_ctx to be able to safely free/remove the timed
250 * event in all 3 cases. */
251 talloc_free(tmp_ctx
);
256 static uint8_t get_break_level1_to_none_count(struct torture_context
*tctx
)
258 return torture_setting_bool(tctx
, "2_step_break_to_none", false) ?
262 static bool test_raw_oplock_exclusive1(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
264 const char *fname
= BASEDIR
"\\test_exclusive1.dat";
268 union smb_unlink unl
;
271 if (!torture_setup_dir(cli1
, BASEDIR
)) {
276 smbcli_unlink(cli1
->tree
, fname
);
278 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
283 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
284 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
285 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
286 io
.ntcreatex
.in
.alloc_size
= 0;
287 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
288 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
289 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
290 io
.ntcreatex
.in
.create_options
= 0;
291 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
292 io
.ntcreatex
.in
.security_flags
= 0;
293 io
.ntcreatex
.in
.fname
= fname
;
295 torture_comment(tctx
, "EXCLUSIVE1: open a file with an exclusive oplock (share mode: none)\n");
296 ZERO_STRUCT(break_info
);
297 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
299 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
300 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
301 fnum
= io
.ntcreatex
.out
.file
.fnum
;
302 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
304 torture_comment(tctx
, "a 2nd open should not cause a break\n");
305 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
306 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
307 torture_wait_for_oplock_break(tctx
);
308 CHECK_VAL(break_info
.count
, 0);
309 CHECK_VAL(break_info
.failures
, 0);
311 torture_comment(tctx
, "unlink it - should also be no break\n");
312 unl
.unlink
.in
.pattern
= fname
;
313 unl
.unlink
.in
.attrib
= 0;
314 status
= smb_raw_unlink(cli2
->tree
, &unl
);
315 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
316 torture_wait_for_oplock_break(tctx
);
317 CHECK_VAL(break_info
.count
, 0);
318 CHECK_VAL(break_info
.failures
, 0);
320 smbcli_close(cli1
->tree
, fnum
);
323 smb_raw_exit(cli1
->session
);
324 smb_raw_exit(cli2
->session
);
325 smbcli_deltree(cli1
->tree
, BASEDIR
);
329 static bool test_raw_oplock_exclusive2(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
331 const char *fname
= BASEDIR
"\\test_exclusive2.dat";
335 union smb_unlink unl
;
336 uint16_t fnum
=0, fnum2
=0;
338 if (!torture_setup_dir(cli1
, BASEDIR
)) {
343 smbcli_unlink(cli1
->tree
, fname
);
345 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
350 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
351 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
352 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
353 io
.ntcreatex
.in
.alloc_size
= 0;
354 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
355 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
356 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
357 io
.ntcreatex
.in
.create_options
= 0;
358 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
359 io
.ntcreatex
.in
.security_flags
= 0;
360 io
.ntcreatex
.in
.fname
= fname
;
362 torture_comment(tctx
, "EXCLUSIVE2: open a file with an exclusive oplock (share mode: all)\n");
363 ZERO_STRUCT(break_info
);
364 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
365 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
366 NTCREATEX_SHARE_ACCESS_WRITE
|
367 NTCREATEX_SHARE_ACCESS_DELETE
;
369 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
370 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
371 fnum
= io
.ntcreatex
.out
.file
.fnum
;
372 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
374 torture_comment(tctx
, "a 2nd open should cause a break to level 2\n");
375 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
376 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
377 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
378 torture_wait_for_oplock_break(tctx
);
379 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
380 CHECK_VAL(break_info
.count
, 1);
381 CHECK_VAL(break_info
.fnum
, fnum
);
382 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
383 CHECK_VAL(break_info
.failures
, 0);
384 ZERO_STRUCT(break_info
);
386 /* now we have 2 level II oplocks... */
387 torture_comment(tctx
, "try to unlink it - should not cause a break, but a sharing violation\n");
388 unl
.unlink
.in
.pattern
= fname
;
389 unl
.unlink
.in
.attrib
= 0;
390 status
= smb_raw_unlink(cli2
->tree
, &unl
);
391 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
392 torture_wait_for_oplock_break(tctx
);
393 CHECK_VAL(break_info
.count
, 0);
394 CHECK_VAL(break_info
.failures
, 0);
396 torture_comment(tctx
, "close 1st handle\n");
397 smbcli_close(cli1
->tree
, fnum
);
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 2nd handle\n");
409 smbcli_close(cli2
->tree
, fnum2
);
411 torture_comment(tctx
, "unlink it\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_OK
);
416 torture_wait_for_oplock_break(tctx
);
417 CHECK_VAL(break_info
.count
, 0);
418 CHECK_VAL(break_info
.failures
, 0);
421 smb_raw_exit(cli1
->session
);
422 smb_raw_exit(cli2
->session
);
423 smbcli_deltree(cli1
->tree
, BASEDIR
);
427 static bool test_raw_oplock_exclusive3(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
429 const char *fname
= BASEDIR
"\\test_exclusive3.dat";
433 union smb_setfileinfo sfi
;
436 if (!torture_setup_dir(cli1
, BASEDIR
)) {
441 smbcli_unlink(cli1
->tree
, fname
);
443 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
448 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
449 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
450 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
451 io
.ntcreatex
.in
.alloc_size
= 0;
452 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
453 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_WRITE
;
454 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
455 io
.ntcreatex
.in
.create_options
= 0;
456 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
457 io
.ntcreatex
.in
.security_flags
= 0;
458 io
.ntcreatex
.in
.fname
= fname
;
460 torture_comment(tctx
, "EXCLUSIVE3: open a file with an exclusive oplock (share mode: none)\n");
462 ZERO_STRUCT(break_info
);
463 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
465 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
466 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
467 fnum
= io
.ntcreatex
.out
.file
.fnum
;
468 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
470 torture_comment(tctx
, "setpathinfo EOF should trigger a break to none\n");
472 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
473 sfi
.generic
.in
.file
.path
= fname
;
474 sfi
.end_of_file_info
.in
.size
= 100;
476 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
478 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
479 torture_wait_for_oplock_break(tctx
);
480 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
481 CHECK_VAL(break_info
.failures
, 0);
482 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
484 smbcli_close(cli1
->tree
, fnum
);
487 smb_raw_exit(cli1
->session
);
488 smb_raw_exit(cli2
->session
);
489 smbcli_deltree(cli1
->tree
, BASEDIR
);
493 static bool test_raw_oplock_exclusive4(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
495 const char *fname
= BASEDIR
"\\test_exclusive4.dat";
499 uint16_t fnum
=0, fnum2
=0;
501 if (!torture_setup_dir(cli1
, BASEDIR
)) {
506 smbcli_unlink(cli1
->tree
, fname
);
508 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
513 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
514 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
515 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
516 io
.ntcreatex
.in
.alloc_size
= 0;
517 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
518 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
519 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
520 io
.ntcreatex
.in
.create_options
= 0;
521 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
522 io
.ntcreatex
.in
.security_flags
= 0;
523 io
.ntcreatex
.in
.fname
= fname
;
525 torture_comment(tctx
, "EXCLUSIVE4: open with exclusive oplock\n");
526 ZERO_STRUCT(break_info
);
527 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
529 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
530 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
531 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
532 fnum
= io
.ntcreatex
.out
.file
.fnum
;
533 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
535 ZERO_STRUCT(break_info
);
536 torture_comment(tctx
, "second open with attributes only shouldn't cause oplock break\n");
538 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
539 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
540 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
541 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
542 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
543 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
544 torture_wait_for_oplock_break(tctx
);
545 CHECK_VAL(break_info
.count
, 0);
546 CHECK_VAL(break_info
.failures
, 0);
548 smbcli_close(cli1
->tree
, fnum
);
549 smbcli_close(cli2
->tree
, fnum2
);
552 smb_raw_exit(cli1
->session
);
553 smb_raw_exit(cli2
->session
);
554 smbcli_deltree(cli1
->tree
, BASEDIR
);
558 static bool test_raw_oplock_exclusive5(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
560 const char *fname
= BASEDIR
"\\test_exclusive5.dat";
564 uint16_t fnum
=0, fnum2
=0;
566 if (!torture_setup_dir(cli1
, BASEDIR
)) {
571 smbcli_unlink(cli1
->tree
, fname
);
573 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
574 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
579 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
580 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
581 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
582 io
.ntcreatex
.in
.alloc_size
= 0;
583 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
584 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
585 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
586 io
.ntcreatex
.in
.create_options
= 0;
587 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
588 io
.ntcreatex
.in
.security_flags
= 0;
589 io
.ntcreatex
.in
.fname
= fname
;
591 torture_comment(tctx
, "EXCLUSIVE5: open with exclusive oplock\n");
592 ZERO_STRUCT(break_info
);
593 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
596 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
597 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
598 NTCREATEX_SHARE_ACCESS_WRITE
|
599 NTCREATEX_SHARE_ACCESS_DELETE
;
600 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
601 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
602 fnum
= io
.ntcreatex
.out
.file
.fnum
;
603 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
605 ZERO_STRUCT(break_info
);
607 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
609 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
610 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
611 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
612 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
613 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
614 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
615 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
616 torture_wait_for_oplock_break(tctx
);
617 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
618 CHECK_VAL(break_info
.failures
, 0);
620 smbcli_close(cli1
->tree
, fnum
);
621 smbcli_close(cli2
->tree
, fnum2
);
624 smb_raw_exit(cli1
->session
);
625 smb_raw_exit(cli2
->session
);
626 smbcli_deltree(cli1
->tree
, BASEDIR
);
630 static bool test_raw_oplock_exclusive6(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
632 const char *fname1
= BASEDIR
"\\test_exclusive6_1.dat";
633 const char *fname2
= BASEDIR
"\\test_exclusive6_2.dat";
640 if (!torture_setup_dir(cli1
, BASEDIR
)) {
645 smbcli_unlink(cli1
->tree
, fname1
);
646 smbcli_unlink(cli1
->tree
, fname2
);
648 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
653 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
654 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
655 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
656 io
.ntcreatex
.in
.alloc_size
= 0;
657 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
658 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
659 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
660 io
.ntcreatex
.in
.create_options
= 0;
661 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
662 io
.ntcreatex
.in
.security_flags
= 0;
663 io
.ntcreatex
.in
.fname
= fname1
;
665 torture_comment(tctx
, "EXCLUSIVE6: open a file with an exclusive "
666 "oplock (share mode: none)\n");
667 ZERO_STRUCT(break_info
);
668 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
670 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
671 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
672 fnum
= io
.ntcreatex
.out
.file
.fnum
;
673 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
675 torture_comment(tctx
, "rename should not generate a break but get a "
676 "sharing violation\n");
678 rn
.generic
.level
= RAW_RENAME_RENAME
;
679 rn
.rename
.in
.pattern1
= fname1
;
680 rn
.rename
.in
.pattern2
= fname2
;
681 rn
.rename
.in
.attrib
= 0;
683 torture_comment(tctx
, "trying rename while first file open\n");
684 status
= smb_raw_rename(cli2
->tree
, &rn
);
686 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
687 torture_wait_for_oplock_break(tctx
);
688 CHECK_VAL(break_info
.count
, 0);
689 CHECK_VAL(break_info
.failures
, 0);
691 smbcli_close(cli1
->tree
, fnum
);
694 smb_raw_exit(cli1
->session
);
695 smb_raw_exit(cli2
->session
);
696 smbcli_deltree(cli1
->tree
, BASEDIR
);
701 * Exclusive version of batch19
703 static bool test_raw_oplock_exclusive7(struct torture_context
*tctx
,
704 struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
706 const char *fname1
= BASEDIR
"\\test_exclusiv6_1.dat";
707 const char *fname2
= BASEDIR
"\\test_exclusiv6_2.dat";
708 const char *fname3
= BASEDIR
"\\test_exclusiv6_3.dat";
712 union smb_fileinfo qfi
;
713 union smb_setfileinfo sfi
;
717 if (!torture_setup_dir(cli1
, BASEDIR
)) {
722 smbcli_unlink(cli1
->tree
, fname1
);
723 smbcli_unlink(cli1
->tree
, fname2
);
724 smbcli_unlink(cli1
->tree
, fname3
);
726 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
732 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
733 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
734 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
735 io
.ntcreatex
.in
.alloc_size
= 0;
736 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
737 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
738 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
739 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
740 io
.ntcreatex
.in
.create_options
= 0;
741 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
742 io
.ntcreatex
.in
.security_flags
= 0;
743 io
.ntcreatex
.in
.fname
= fname1
;
745 torture_comment(tctx
, "open a file with an exclusive oplock (share "
747 ZERO_STRUCT(break_info
);
748 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
749 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
750 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
751 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
752 fnum
= io
.ntcreatex
.out
.file
.fnum
;
753 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
755 torture_comment(tctx
, "setpathinfo rename info should trigger a break "
758 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
759 sfi
.generic
.in
.file
.path
= fname1
;
760 sfi
.rename_information
.in
.overwrite
= 0;
761 sfi
.rename_information
.in
.root_fid
= 0;
762 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
764 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
765 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
767 torture_wait_for_oplock_break(tctx
);
768 CHECK_VAL(break_info
.failures
, 0);
770 if (TARGET_IS_WINXP(tctx
)) {
771 /* XP incorrectly breaks to level2. */
772 CHECK_VAL(break_info
.count
, 1);
773 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
775 /* Exclusive oplocks should not be broken on rename. */
776 CHECK_VAL(break_info
.failures
, 0);
777 CHECK_VAL(break_info
.count
, 0);
781 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
782 qfi
.generic
.in
.file
.fnum
= fnum
;
784 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
785 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
786 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
788 /* Try breaking to level2 and then see if rename breaks the level2.*/
789 ZERO_STRUCT(break_info
);
790 io
.ntcreatex
.in
.fname
= fname2
;
791 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
792 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
793 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
794 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
796 torture_wait_for_oplock_break(tctx
);
797 CHECK_VAL(break_info
.failures
, 0);
799 if (TARGET_IS_WINXP(tctx
)) {
800 /* XP already broke to level2. */
801 CHECK_VAL(break_info
.failures
, 0);
802 CHECK_VAL(break_info
.count
, 0);
804 /* Break to level 2 expected. */
805 CHECK_VAL(break_info
.count
, 1);
806 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
809 ZERO_STRUCT(break_info
);
810 sfi
.generic
.in
.file
.path
= fname2
;
811 sfi
.rename_information
.in
.overwrite
= 0;
812 sfi
.rename_information
.in
.root_fid
= 0;
813 sfi
.rename_information
.in
.new_name
= fname1
+strlen(BASEDIR
)+1;
815 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
816 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
818 /* Level2 oplocks are not broken on rename. */
819 torture_wait_for_oplock_break(tctx
);
820 CHECK_VAL(break_info
.failures
, 0);
821 CHECK_VAL(break_info
.count
, 0);
823 /* Close and re-open file with oplock. */
824 smbcli_close(cli1
->tree
, fnum
);
825 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
826 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
827 fnum
= io
.ntcreatex
.out
.file
.fnum
;
828 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
830 torture_comment(tctx
, "setfileinfo rename info on a client's own fid "
831 "should not trigger a break nor a violation\n");
832 ZERO_STRUCT(break_info
);
834 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
835 sfi
.generic
.in
.file
.fnum
= fnum
;
836 sfi
.rename_information
.in
.overwrite
= 0;
837 sfi
.rename_information
.in
.root_fid
= 0;
838 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
840 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
841 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
843 torture_wait_for_oplock_break(tctx
);
844 if (TARGET_IS_WINXP(tctx
)) {
845 /* XP incorrectly breaks to level2. */
846 CHECK_VAL(break_info
.count
, 1);
847 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
849 CHECK_VAL(break_info
.count
, 0);
853 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
854 qfi
.generic
.in
.file
.fnum
= fnum
;
856 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
857 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
858 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
861 smbcli_close(cli1
->tree
, fnum
);
862 smbcli_close(cli2
->tree
, fnum2
);
864 smb_raw_exit(cli1
->session
);
865 smb_raw_exit(cli2
->session
);
866 smbcli_deltree(cli1
->tree
, BASEDIR
);
870 static bool test_raw_oplock_exclusive8(struct torture_context
*tctx
,
871 struct smbcli_state
*cli1
,
872 struct smbcli_state
*cli2
)
874 const char *fname
= BASEDIR
"\\test_exclusive8.dat";
882 if (!torture_setup_dir(cli1
, BASEDIR
)) {
887 smbcli_unlink(cli1
->tree
, fname
);
889 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
895 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
896 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
897 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
898 io
.ntcreatex
.in
.alloc_size
= 0;
899 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
900 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
901 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
902 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
903 io
.ntcreatex
.in
.create_options
= 0;
904 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
905 io
.ntcreatex
.in
.security_flags
= 0;
906 io
.ntcreatex
.in
.fname
= fname
;
908 torture_comment(tctx
, "open a file with an exclusive oplock (share "
910 ZERO_STRUCT(break_info
);
911 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
912 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
913 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
914 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
915 fnum1
= io
.ntcreatex
.out
.file
.fnum
;
916 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
918 torture_comment(tctx
, "second open with delete should trigger a "
921 io
.ntcreatex
.in
.access_mask
= SEC_STD_DELETE
;
922 io
.ntcreatex
.in
.flags
= 0;
923 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
924 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
925 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
926 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
927 CHECK_VAL(break_info
.failures
, 0);
928 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
930 /* Trigger a little panic in "old" samba code.. */
931 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
932 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
933 fnum3
= io
.ntcreatex
.out
.file
.fnum
;
935 smbcli_close(cli2
->tree
, fnum3
);
936 smbcli_close(cli2
->tree
, fnum2
);
937 smbcli_close(cli1
->tree
, fnum1
);
940 smbcli_deltree(cli1
->tree
, BASEDIR
);
941 smb_raw_exit(cli1
->session
);
942 smb_raw_exit(cli2
->session
);
946 static bool test_raw_oplock_batch1(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
948 const char *fname
= BASEDIR
"\\test_batch1.dat";
952 union smb_unlink unl
;
956 if (!torture_setup_dir(cli1
, BASEDIR
)) {
961 smbcli_unlink(cli1
->tree
, fname
);
963 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
968 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
969 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
970 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
971 io
.ntcreatex
.in
.alloc_size
= 0;
972 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
973 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
974 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
975 io
.ntcreatex
.in
.create_options
= 0;
976 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
977 io
.ntcreatex
.in
.security_flags
= 0;
978 io
.ntcreatex
.in
.fname
= fname
;
981 with a batch oplock we get a break
983 torture_comment(tctx
, "BATCH1: open with batch oplock\n");
984 ZERO_STRUCT(break_info
);
985 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
986 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
987 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
988 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
989 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
990 fnum
= io
.ntcreatex
.out
.file
.fnum
;
991 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
993 torture_comment(tctx
, "unlink should generate a break\n");
994 unl
.unlink
.in
.pattern
= fname
;
995 unl
.unlink
.in
.attrib
= 0;
996 status
= smb_raw_unlink(cli2
->tree
, &unl
);
997 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
999 torture_wait_for_oplock_break(tctx
);
1000 CHECK_VAL(break_info
.count
, 1);
1001 CHECK_VAL(break_info
.fnum
, fnum
);
1002 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
1003 CHECK_VAL(break_info
.failures
, 0);
1005 torture_comment(tctx
, "2nd unlink should not generate a break\n");
1006 ZERO_STRUCT(break_info
);
1007 status
= smb_raw_unlink(cli2
->tree
, &unl
);
1008 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
1010 torture_wait_for_oplock_break(tctx
);
1011 CHECK_VAL(break_info
.count
, 0);
1013 torture_comment(tctx
, "writing should generate a self break to none\n");
1014 smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
1016 torture_wait_for_oplock_break(tctx
);
1017 torture_wait_for_oplock_break(tctx
);
1018 CHECK_VAL(break_info
.count
, 1);
1019 CHECK_VAL(break_info
.fnum
, fnum
);
1020 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
1021 CHECK_VAL(break_info
.failures
, 0);
1023 smbcli_close(cli1
->tree
, fnum
);
1026 smb_raw_exit(cli1
->session
);
1027 smb_raw_exit(cli2
->session
);
1028 smbcli_deltree(cli1
->tree
, BASEDIR
);
1032 static bool test_raw_oplock_batch2(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1034 const char *fname
= BASEDIR
"\\test_batch2.dat";
1038 union smb_unlink unl
;
1042 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1047 smbcli_unlink(cli1
->tree
, fname
);
1049 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1052 base ntcreatex parms
1054 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1055 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1056 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1057 io
.ntcreatex
.in
.alloc_size
= 0;
1058 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1059 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1060 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1061 io
.ntcreatex
.in
.create_options
= 0;
1062 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1063 io
.ntcreatex
.in
.security_flags
= 0;
1064 io
.ntcreatex
.in
.fname
= fname
;
1066 torture_comment(tctx
, "BATCH2: open with batch oplock\n");
1067 ZERO_STRUCT(break_info
);
1068 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1069 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1070 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1071 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1072 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1073 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1074 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1076 torture_comment(tctx
, "unlink should generate a break, which we ack as break to none\n");
1077 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_none
, cli1
->tree
);
1078 unl
.unlink
.in
.pattern
= fname
;
1079 unl
.unlink
.in
.attrib
= 0;
1080 status
= smb_raw_unlink(cli2
->tree
, &unl
);
1081 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
1083 torture_wait_for_oplock_break(tctx
);
1084 CHECK_VAL(break_info
.count
, 1);
1085 CHECK_VAL(break_info
.fnum
, fnum
);
1086 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
1087 CHECK_VAL(break_info
.failures
, 0);
1089 torture_comment(tctx
, "2nd unlink should not generate a break\n");
1090 ZERO_STRUCT(break_info
);
1091 status
= smb_raw_unlink(cli2
->tree
, &unl
);
1092 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
1094 torture_wait_for_oplock_break(tctx
);
1095 CHECK_VAL(break_info
.count
, 0);
1097 torture_comment(tctx
, "writing should not generate a break\n");
1098 smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
1100 torture_wait_for_oplock_break(tctx
);
1101 CHECK_VAL(break_info
.count
, 0);
1103 smbcli_close(cli1
->tree
, fnum
);
1106 smb_raw_exit(cli1
->session
);
1107 smb_raw_exit(cli2
->session
);
1108 smbcli_deltree(cli1
->tree
, BASEDIR
);
1112 static bool test_raw_oplock_batch3(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1114 const char *fname
= BASEDIR
"\\test_batch3.dat";
1118 union smb_unlink unl
;
1121 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1126 smbcli_unlink(cli1
->tree
, fname
);
1128 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1131 base ntcreatex parms
1133 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1134 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1135 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1136 io
.ntcreatex
.in
.alloc_size
= 0;
1137 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1138 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1139 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1140 io
.ntcreatex
.in
.create_options
= 0;
1141 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1142 io
.ntcreatex
.in
.security_flags
= 0;
1143 io
.ntcreatex
.in
.fname
= fname
;
1145 torture_comment(tctx
, "BATCH3: if we close on break then the unlink can succeed\n");
1146 ZERO_STRUCT(break_info
);
1147 smbcli_oplock_handler(cli1
->transport
, oplock_handler_close
, cli1
->tree
);
1148 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1149 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1150 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1151 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1152 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1153 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1154 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1156 unl
.unlink
.in
.pattern
= fname
;
1157 unl
.unlink
.in
.attrib
= 0;
1158 ZERO_STRUCT(break_info
);
1159 status
= smb_raw_unlink(cli2
->tree
, &unl
);
1160 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1162 torture_wait_for_oplock_break(tctx
);
1163 CHECK_VAL(break_info
.count
, 1);
1164 CHECK_VAL(break_info
.fnum
, fnum
);
1165 CHECK_VAL(break_info
.level
, 1);
1166 CHECK_VAL(break_info
.failures
, 0);
1168 smbcli_close(cli1
->tree
, fnum
);
1171 smb_raw_exit(cli1
->session
);
1172 smb_raw_exit(cli2
->session
);
1173 smbcli_deltree(cli1
->tree
, BASEDIR
);
1177 static bool test_raw_oplock_batch4(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1179 const char *fname
= BASEDIR
"\\test_batch4.dat";
1186 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1191 smbcli_unlink(cli1
->tree
, fname
);
1193 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1196 base ntcreatex parms
1198 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1199 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1200 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1201 io
.ntcreatex
.in
.alloc_size
= 0;
1202 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1203 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1204 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1205 io
.ntcreatex
.in
.create_options
= 0;
1206 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1207 io
.ntcreatex
.in
.security_flags
= 0;
1208 io
.ntcreatex
.in
.fname
= fname
;
1210 torture_comment(tctx
, "BATCH4: a self read should not cause a break\n");
1211 ZERO_STRUCT(break_info
);
1212 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1214 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1215 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1216 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1217 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1218 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1219 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1220 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1222 rd
.readx
.level
= RAW_READ_READX
;
1223 rd
.readx
.in
.file
.fnum
= fnum
;
1224 rd
.readx
.in
.mincnt
= 1;
1225 rd
.readx
.in
.maxcnt
= 1;
1226 rd
.readx
.in
.offset
= 0;
1227 rd
.readx
.in
.remaining
= 0;
1228 rd
.readx
.in
.read_for_execute
= false;
1229 status
= smb_raw_read(cli1
->tree
, &rd
);
1230 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1231 torture_wait_for_oplock_break(tctx
);
1232 CHECK_VAL(break_info
.count
, 0);
1233 CHECK_VAL(break_info
.failures
, 0);
1235 smbcli_close(cli1
->tree
, fnum
);
1238 smb_raw_exit(cli1
->session
);
1239 smb_raw_exit(cli2
->session
);
1240 smbcli_deltree(cli1
->tree
, BASEDIR
);
1244 static bool test_raw_oplock_batch5(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1246 const char *fname
= BASEDIR
"\\test_batch5.dat";
1252 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1257 smbcli_unlink(cli1
->tree
, fname
);
1259 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1262 base ntcreatex parms
1264 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1265 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1266 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1267 io
.ntcreatex
.in
.alloc_size
= 0;
1268 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1269 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1270 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1271 io
.ntcreatex
.in
.create_options
= 0;
1272 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1273 io
.ntcreatex
.in
.security_flags
= 0;
1274 io
.ntcreatex
.in
.fname
= fname
;
1276 torture_comment(tctx
, "BATCH5: a 2nd open should give a break\n");
1277 ZERO_STRUCT(break_info
);
1278 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1280 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1281 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1282 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1283 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1284 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1285 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1286 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1288 ZERO_STRUCT(break_info
);
1290 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
1291 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1292 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
1294 torture_wait_for_oplock_break(tctx
);
1295 CHECK_VAL(break_info
.count
, 1);
1296 CHECK_VAL(break_info
.fnum
, fnum
);
1297 CHECK_VAL(break_info
.level
, 1);
1298 CHECK_VAL(break_info
.failures
, 0);
1300 smbcli_close(cli1
->tree
, fnum
);
1303 smb_raw_exit(cli1
->session
);
1304 smb_raw_exit(cli2
->session
);
1305 smbcli_deltree(cli1
->tree
, BASEDIR
);
1309 static bool test_raw_oplock_batch6(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1311 const char *fname
= BASEDIR
"\\test_batch6.dat";
1315 uint16_t fnum
=0, fnum2
=0;
1318 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1323 smbcli_unlink(cli1
->tree
, fname
);
1325 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1326 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
1329 base ntcreatex parms
1331 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1332 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1333 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1334 io
.ntcreatex
.in
.alloc_size
= 0;
1335 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1336 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1337 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1338 io
.ntcreatex
.in
.create_options
= 0;
1339 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1340 io
.ntcreatex
.in
.security_flags
= 0;
1341 io
.ntcreatex
.in
.fname
= fname
;
1343 torture_comment(tctx
, "BATCH6: a 2nd open should give a break to level II if the first open allowed shared read\n");
1344 ZERO_STRUCT(break_info
);
1346 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
| SEC_RIGHTS_FILE_WRITE
;
1347 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
1348 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1349 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1350 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1351 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1352 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1353 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1354 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1356 ZERO_STRUCT(break_info
);
1358 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1359 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1360 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1361 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1363 //torture_wait_for_oplock_break(tctx);
1364 CHECK_VAL(break_info
.count
, 1);
1365 CHECK_VAL(break_info
.fnum
, fnum
);
1366 CHECK_VAL(break_info
.level
, 1);
1367 CHECK_VAL(break_info
.failures
, 0);
1368 ZERO_STRUCT(break_info
);
1370 torture_comment(tctx
, "write should trigger a break to none on both\n");
1371 smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
1373 /* We expect two breaks */
1374 torture_wait_for_oplock_break(tctx
);
1375 torture_wait_for_oplock_break(tctx
);
1377 CHECK_VAL(break_info
.count
, 2);
1378 CHECK_VAL(break_info
.level
, 0);
1379 CHECK_VAL(break_info
.failures
, 0);
1381 smbcli_close(cli1
->tree
, fnum
);
1382 smbcli_close(cli2
->tree
, fnum2
);
1385 smb_raw_exit(cli1
->session
);
1386 smb_raw_exit(cli2
->session
);
1387 smbcli_deltree(cli1
->tree
, BASEDIR
);
1391 static bool test_raw_oplock_batch7(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1393 const char *fname
= BASEDIR
"\\test_batch7.dat";
1397 uint16_t fnum
=0, fnum2
=0;
1399 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1404 smbcli_unlink(cli1
->tree
, fname
);
1406 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1409 base ntcreatex parms
1411 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1412 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1413 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1414 io
.ntcreatex
.in
.alloc_size
= 0;
1415 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1416 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1417 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1418 io
.ntcreatex
.in
.create_options
= 0;
1419 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1420 io
.ntcreatex
.in
.security_flags
= 0;
1421 io
.ntcreatex
.in
.fname
= fname
;
1423 torture_comment(tctx
, "BATCH7: a 2nd open should get an oplock when we close instead of ack\n");
1424 ZERO_STRUCT(break_info
);
1425 smbcli_oplock_handler(cli1
->transport
, oplock_handler_close
, cli1
->tree
);
1427 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1428 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1429 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1430 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1431 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1432 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1433 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1434 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1435 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1437 ZERO_STRUCT(break_info
);
1439 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1440 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1441 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1442 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1443 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1444 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1445 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1447 torture_wait_for_oplock_break(tctx
);
1448 CHECK_VAL(break_info
.count
, 1);
1449 CHECK_VAL(break_info
.fnum
, fnum2
);
1450 CHECK_VAL(break_info
.level
, 1);
1451 CHECK_VAL(break_info
.failures
, 0);
1453 smbcli_close(cli2
->tree
, fnum
);
1456 smb_raw_exit(cli1
->session
);
1457 smb_raw_exit(cli2
->session
);
1458 smbcli_deltree(cli1
->tree
, BASEDIR
);
1462 static bool test_raw_oplock_batch8(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1464 const char *fname
= BASEDIR
"\\test_batch8.dat";
1468 uint16_t fnum
=0, fnum2
=0;
1470 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1475 smbcli_unlink(cli1
->tree
, fname
);
1477 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1480 base ntcreatex parms
1482 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1483 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1484 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1485 io
.ntcreatex
.in
.alloc_size
= 0;
1486 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1487 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1488 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1489 io
.ntcreatex
.in
.create_options
= 0;
1490 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1491 io
.ntcreatex
.in
.security_flags
= 0;
1492 io
.ntcreatex
.in
.fname
= fname
;
1494 torture_comment(tctx
, "BATCH8: open with batch oplock\n");
1495 ZERO_STRUCT(break_info
);
1496 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1498 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1499 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1500 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1501 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1502 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1503 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1504 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1506 ZERO_STRUCT(break_info
);
1507 torture_comment(tctx
, "second open with attributes only shouldn't cause oplock break\n");
1509 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1510 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1511 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1512 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1513 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1514 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1515 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1516 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
1517 torture_wait_for_oplock_break(tctx
);
1518 CHECK_VAL(break_info
.count
, 0);
1519 CHECK_VAL(break_info
.failures
, 0);
1521 smbcli_close(cli1
->tree
, fnum
);
1522 smbcli_close(cli2
->tree
, fnum2
);
1525 smb_raw_exit(cli1
->session
);
1526 smb_raw_exit(cli2
->session
);
1527 smbcli_deltree(cli1
->tree
, BASEDIR
);
1531 static bool test_raw_oplock_batch9(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1533 const char *fname
= BASEDIR
"\\test_batch9.dat";
1537 uint16_t fnum
=0, fnum2
=0;
1540 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1545 smbcli_unlink(cli1
->tree
, fname
);
1547 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1550 base ntcreatex parms
1552 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1553 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1554 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1555 io
.ntcreatex
.in
.alloc_size
= 0;
1556 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1557 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1558 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1559 io
.ntcreatex
.in
.create_options
= 0;
1560 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1561 io
.ntcreatex
.in
.security_flags
= 0;
1562 io
.ntcreatex
.in
.fname
= fname
;
1564 torture_comment(tctx
, "BATCH9: open with attributes only can create file\n");
1566 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1567 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1568 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1569 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1570 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1571 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1572 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1573 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1574 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1576 torture_comment(tctx
, "Subsequent normal open should break oplock on attribute only open to level II\n");
1578 ZERO_STRUCT(break_info
);
1579 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1581 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1582 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1583 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1584 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1585 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1586 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1587 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1588 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1589 torture_wait_for_oplock_break(tctx
);
1590 CHECK_VAL(break_info
.count
, 1);
1591 CHECK_VAL(break_info
.fnum
, fnum
);
1592 CHECK_VAL(break_info
.failures
, 0);
1593 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
1594 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1595 smbcli_close(cli2
->tree
, fnum2
);
1597 torture_comment(tctx
, "third oplocked open should grant level2 without break\n");
1598 ZERO_STRUCT(break_info
);
1599 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1600 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
1601 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1602 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1603 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1604 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1605 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1606 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1607 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1608 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1609 torture_wait_for_oplock_break(tctx
);
1610 CHECK_VAL(break_info
.count
, 0);
1611 CHECK_VAL(break_info
.failures
, 0);
1612 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1614 ZERO_STRUCT(break_info
);
1616 torture_comment(tctx
, "write should trigger a break to none on both\n");
1617 smbcli_write(cli2
->tree
, fnum2
, 0, &c
, 0, 1);
1619 /* We expect two breaks */
1620 torture_wait_for_oplock_break(tctx
);
1621 torture_wait_for_oplock_break(tctx
);
1623 CHECK_VAL(break_info
.count
, 2);
1624 CHECK_VAL(break_info
.level
, 0);
1625 CHECK_VAL(break_info
.failures
, 0);
1627 smbcli_close(cli1
->tree
, fnum
);
1628 smbcli_close(cli2
->tree
, fnum2
);
1631 smb_raw_exit(cli1
->session
);
1632 smb_raw_exit(cli2
->session
);
1633 smbcli_deltree(cli1
->tree
, BASEDIR
);
1637 static bool test_raw_oplock_batch10(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1639 const char *fname
= BASEDIR
"\\test_batch10.dat";
1643 uint16_t fnum
=0, fnum2
=0;
1645 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1650 smbcli_unlink(cli1
->tree
, fname
);
1652 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1655 base ntcreatex parms
1657 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1658 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1659 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1660 io
.ntcreatex
.in
.alloc_size
= 0;
1661 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1662 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1663 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1664 io
.ntcreatex
.in
.create_options
= 0;
1665 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1666 io
.ntcreatex
.in
.security_flags
= 0;
1667 io
.ntcreatex
.in
.fname
= fname
;
1669 torture_comment(tctx
, "BATCH10: Open with oplock after a non-oplock open should grant level2\n");
1670 ZERO_STRUCT(break_info
);
1671 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
1672 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1673 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1674 NTCREATEX_SHARE_ACCESS_WRITE
|
1675 NTCREATEX_SHARE_ACCESS_DELETE
;
1676 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1677 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1678 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1679 torture_wait_for_oplock_break(tctx
);
1680 CHECK_VAL(break_info
.count
, 0);
1681 CHECK_VAL(break_info
.failures
, 0);
1682 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, 0);
1684 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
1686 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1687 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1688 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1689 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1690 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1691 NTCREATEX_SHARE_ACCESS_WRITE
|
1692 NTCREATEX_SHARE_ACCESS_DELETE
;
1693 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1694 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1695 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1696 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1697 torture_wait_for_oplock_break(tctx
);
1698 CHECK_VAL(break_info
.count
, 0);
1699 CHECK_VAL(break_info
.failures
, 0);
1700 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1702 torture_comment(tctx
, "write should trigger a break to none\n");
1705 wr
.write
.level
= RAW_WRITE_WRITE
;
1706 wr
.write
.in
.file
.fnum
= fnum
;
1707 wr
.write
.in
.count
= 1;
1708 wr
.write
.in
.offset
= 0;
1709 wr
.write
.in
.remaining
= 0;
1710 wr
.write
.in
.data
= (const uint8_t *)"x";
1711 status
= smb_raw_write(cli1
->tree
, &wr
);
1712 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1715 torture_wait_for_oplock_break(tctx
);
1717 CHECK_VAL(break_info
.count
, 1);
1718 CHECK_VAL(break_info
.fnum
, fnum2
);
1719 CHECK_VAL(break_info
.level
, 0);
1720 CHECK_VAL(break_info
.failures
, 0);
1722 smbcli_close(cli1
->tree
, fnum
);
1723 smbcli_close(cli2
->tree
, fnum2
);
1726 smb_raw_exit(cli1
->session
);
1727 smb_raw_exit(cli2
->session
);
1728 smbcli_deltree(cli1
->tree
, BASEDIR
);
1732 static bool test_raw_oplock_batch11(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1734 const char *fname
= BASEDIR
"\\test_batch11.dat";
1738 union smb_setfileinfo sfi
;
1741 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1746 smbcli_unlink(cli1
->tree
, fname
);
1748 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1751 base ntcreatex parms
1753 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1754 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1755 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1756 io
.ntcreatex
.in
.alloc_size
= 0;
1757 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1758 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_WRITE
;
1759 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1760 io
.ntcreatex
.in
.create_options
= 0;
1761 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1762 io
.ntcreatex
.in
.security_flags
= 0;
1763 io
.ntcreatex
.in
.fname
= fname
;
1765 /* Test if a set-eof on pathname breaks an exclusive oplock. */
1766 torture_comment(tctx
, "BATCH11: Test if setpathinfo set EOF breaks oplocks.\n");
1768 ZERO_STRUCT(break_info
);
1770 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1771 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1772 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1773 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1774 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1775 NTCREATEX_SHARE_ACCESS_WRITE
|
1776 NTCREATEX_SHARE_ACCESS_DELETE
;
1777 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1778 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1779 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1780 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1781 torture_wait_for_oplock_break(tctx
);
1782 CHECK_VAL(break_info
.count
, 0);
1783 CHECK_VAL(break_info
.failures
, 0);
1784 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1787 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
1788 sfi
.generic
.in
.file
.path
= fname
;
1789 sfi
.end_of_file_info
.in
.size
= 100;
1791 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
1792 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1794 torture_wait_for_oplock_break(tctx
);
1795 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
1796 CHECK_VAL(break_info
.failures
, 0);
1797 CHECK_VAL(break_info
.level
, 0);
1799 smbcli_close(cli1
->tree
, fnum
);
1802 smb_raw_exit(cli1
->session
);
1803 smb_raw_exit(cli2
->session
);
1804 smbcli_deltree(cli1
->tree
, BASEDIR
);
1808 static bool test_raw_oplock_batch12(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1810 const char *fname
= BASEDIR
"\\test_batch12.dat";
1814 union smb_setfileinfo sfi
;
1817 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1822 smbcli_unlink(cli1
->tree
, fname
);
1824 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1827 base ntcreatex parms
1829 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1830 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1831 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1832 io
.ntcreatex
.in
.alloc_size
= 0;
1833 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1834 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1835 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1836 io
.ntcreatex
.in
.create_options
= 0;
1837 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1838 io
.ntcreatex
.in
.security_flags
= 0;
1839 io
.ntcreatex
.in
.fname
= fname
;
1841 /* Test if a set-allocation size on pathname breaks an exclusive oplock. */
1842 torture_comment(tctx
, "BATCH12: Test if setpathinfo allocation size breaks oplocks.\n");
1844 ZERO_STRUCT(break_info
);
1845 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1847 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1848 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1849 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1850 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1851 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1852 NTCREATEX_SHARE_ACCESS_WRITE
|
1853 NTCREATEX_SHARE_ACCESS_DELETE
;
1854 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1855 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1856 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1857 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1858 torture_wait_for_oplock_break(tctx
);
1859 CHECK_VAL(break_info
.count
, 0);
1860 CHECK_VAL(break_info
.failures
, 0);
1861 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1864 sfi
.generic
.level
= SMB_SFILEINFO_ALLOCATION_INFORMATION
;
1865 sfi
.generic
.in
.file
.path
= fname
;
1866 sfi
.allocation_info
.in
.alloc_size
= 65536 * 8;
1868 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
1869 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1871 torture_wait_for_oplock_break(tctx
);
1872 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
1873 CHECK_VAL(break_info
.failures
, 0);
1874 CHECK_VAL(break_info
.level
, 0);
1876 smbcli_close(cli1
->tree
, fnum
);
1879 smb_raw_exit(cli1
->session
);
1880 smb_raw_exit(cli2
->session
);
1881 smbcli_deltree(cli1
->tree
, BASEDIR
);
1885 static bool test_raw_oplock_batch13(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1887 const char *fname
= BASEDIR
"\\test_batch13.dat";
1891 uint16_t fnum
=0, fnum2
=0;
1893 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1898 smbcli_unlink(cli1
->tree
, fname
);
1900 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1901 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1904 base ntcreatex parms
1906 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1907 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1908 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1909 io
.ntcreatex
.in
.alloc_size
= 0;
1910 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1911 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1912 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1913 io
.ntcreatex
.in
.create_options
= 0;
1914 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1915 io
.ntcreatex
.in
.security_flags
= 0;
1916 io
.ntcreatex
.in
.fname
= fname
;
1918 torture_comment(tctx
, "BATCH13: open with batch oplock\n");
1919 ZERO_STRUCT(break_info
);
1921 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1922 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1923 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1924 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1925 NTCREATEX_SHARE_ACCESS_WRITE
|
1926 NTCREATEX_SHARE_ACCESS_DELETE
;
1927 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1928 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1929 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1930 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1932 ZERO_STRUCT(break_info
);
1934 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_OVERWRITE dispostion causes oplock break\n");
1936 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1937 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1938 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1939 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1940 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1941 NTCREATEX_SHARE_ACCESS_WRITE
|
1942 NTCREATEX_SHARE_ACCESS_DELETE
;
1943 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE
;
1944 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1945 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1946 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1947 torture_wait_for_oplock_break(tctx
);
1948 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1949 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
1950 CHECK_VAL(break_info
.failures
, 0);
1952 smbcli_close(cli1
->tree
, fnum
);
1953 smbcli_close(cli2
->tree
, fnum2
);
1956 smb_raw_exit(cli1
->session
);
1957 smb_raw_exit(cli2
->session
);
1958 smbcli_deltree(cli1
->tree
, BASEDIR
);
1962 static bool test_raw_oplock_batch14(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1964 const char *fname
= BASEDIR
"\\test_batch14.dat";
1968 uint16_t fnum
=0, fnum2
=0;
1970 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1975 smbcli_unlink(cli1
->tree
, fname
);
1977 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1980 base ntcreatex parms
1982 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1983 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1984 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1985 io
.ntcreatex
.in
.alloc_size
= 0;
1986 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1987 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1988 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1989 io
.ntcreatex
.in
.create_options
= 0;
1990 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1991 io
.ntcreatex
.in
.security_flags
= 0;
1992 io
.ntcreatex
.in
.fname
= fname
;
1994 torture_comment(tctx
, "BATCH14: open with batch oplock\n");
1995 ZERO_STRUCT(break_info
);
1997 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1998 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1999 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2000 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2001 NTCREATEX_SHARE_ACCESS_WRITE
|
2002 NTCREATEX_SHARE_ACCESS_DELETE
;
2003 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2004 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2005 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2006 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2008 ZERO_STRUCT(break_info
);
2010 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_SUPERSEDE dispostion causes oplock break\n");
2012 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2013 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2014 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2015 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
2016 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2017 NTCREATEX_SHARE_ACCESS_WRITE
|
2018 NTCREATEX_SHARE_ACCESS_DELETE
;
2019 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE
;
2020 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
2021 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2022 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2023 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
2025 torture_wait_for_oplock_break(tctx
);
2026 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
2027 CHECK_VAL(break_info
.failures
, 0);
2029 smbcli_close(cli1
->tree
, fnum
);
2030 smbcli_close(cli2
->tree
, fnum2
);
2032 smb_raw_exit(cli1
->session
);
2033 smb_raw_exit(cli2
->session
);
2034 smbcli_deltree(cli1
->tree
, BASEDIR
);
2038 static bool test_raw_oplock_batch15(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2040 const char *fname
= BASEDIR
"\\test_batch15.dat";
2044 union smb_fileinfo qfi
;
2047 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2052 smbcli_unlink(cli1
->tree
, fname
);
2054 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2057 base ntcreatex parms
2059 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2060 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2061 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2062 io
.ntcreatex
.in
.alloc_size
= 0;
2063 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2064 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2065 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2066 io
.ntcreatex
.in
.create_options
= 0;
2067 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2068 io
.ntcreatex
.in
.security_flags
= 0;
2069 io
.ntcreatex
.in
.fname
= fname
;
2071 /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
2072 torture_comment(tctx
, "BATCH15: Test if qpathinfo all info breaks a batch oplock (should not).\n");
2074 ZERO_STRUCT(break_info
);
2076 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2077 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2078 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2079 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2080 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2081 NTCREATEX_SHARE_ACCESS_WRITE
|
2082 NTCREATEX_SHARE_ACCESS_DELETE
;
2083 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2084 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
2085 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2086 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2087 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2089 torture_wait_for_oplock_break(tctx
);
2090 CHECK_VAL(break_info
.count
, 0);
2091 CHECK_VAL(break_info
.failures
, 0);
2092 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2095 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2096 qfi
.generic
.in
.file
.path
= fname
;
2098 status
= smb_raw_pathinfo(cli2
->tree
, tctx
, &qfi
);
2099 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2101 torture_wait_for_oplock_break(tctx
);
2102 CHECK_VAL(break_info
.count
, 0);
2104 smbcli_close(cli1
->tree
, fnum
);
2107 smb_raw_exit(cli1
->session
);
2108 smb_raw_exit(cli2
->session
);
2109 smbcli_deltree(cli1
->tree
, BASEDIR
);
2113 static bool test_raw_oplock_batch16(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2115 const char *fname
= BASEDIR
"\\test_batch16.dat";
2119 uint16_t fnum
=0, fnum2
=0;
2121 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2126 smbcli_unlink(cli1
->tree
, fname
);
2128 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2129 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2132 base ntcreatex parms
2134 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2135 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2136 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2137 io
.ntcreatex
.in
.alloc_size
= 0;
2138 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2139 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2140 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2141 io
.ntcreatex
.in
.create_options
= 0;
2142 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2143 io
.ntcreatex
.in
.security_flags
= 0;
2144 io
.ntcreatex
.in
.fname
= fname
;
2146 torture_comment(tctx
, "BATCH16: open with batch oplock\n");
2147 ZERO_STRUCT(break_info
);
2149 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2150 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2151 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2152 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2153 NTCREATEX_SHARE_ACCESS_WRITE
|
2154 NTCREATEX_SHARE_ACCESS_DELETE
;
2155 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2156 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2157 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2158 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2160 ZERO_STRUCT(break_info
);
2162 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
2164 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2165 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2166 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2167 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
2168 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2169 NTCREATEX_SHARE_ACCESS_WRITE
|
2170 NTCREATEX_SHARE_ACCESS_DELETE
;
2171 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
2172 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
2173 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2174 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2175 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
2177 torture_wait_for_oplock_break(tctx
);
2178 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
2179 CHECK_VAL(break_info
.failures
, 0);
2181 smbcli_close(cli1
->tree
, fnum
);
2182 smbcli_close(cli2
->tree
, fnum2
);
2185 smb_raw_exit(cli1
->session
);
2186 smb_raw_exit(cli2
->session
);
2187 smbcli_deltree(cli1
->tree
, BASEDIR
);
2191 static bool test_raw_oplock_batch17(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2193 const char *fname1
= BASEDIR
"\\test_batch17_1.dat";
2194 const char *fname2
= BASEDIR
"\\test_batch17_2.dat";
2198 union smb_rename rn
;
2201 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2206 smbcli_unlink(cli1
->tree
, fname1
);
2207 smbcli_unlink(cli1
->tree
, fname2
);
2209 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2212 base ntcreatex parms
2214 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2215 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2216 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2217 io
.ntcreatex
.in
.alloc_size
= 0;
2218 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2219 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2220 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2221 io
.ntcreatex
.in
.create_options
= 0;
2222 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2223 io
.ntcreatex
.in
.security_flags
= 0;
2224 io
.ntcreatex
.in
.fname
= fname1
;
2226 torture_comment(tctx
, "BATCH17: open a file with an batch oplock (share mode: none)\n");
2228 ZERO_STRUCT(break_info
);
2229 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2230 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2231 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2233 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2234 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2235 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2236 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2238 torture_comment(tctx
, "rename should trigger a break\n");
2240 rn
.generic
.level
= RAW_RENAME_RENAME
;
2241 rn
.rename
.in
.pattern1
= fname1
;
2242 rn
.rename
.in
.pattern2
= fname2
;
2243 rn
.rename
.in
.attrib
= 0;
2245 torture_comment(tctx
, "trying rename while first file open\n");
2246 status
= smb_raw_rename(cli2
->tree
, &rn
);
2247 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
2249 torture_wait_for_oplock_break(tctx
);
2250 CHECK_VAL(break_info
.count
, 1);
2251 CHECK_VAL(break_info
.failures
, 0);
2252 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2254 smbcli_close(cli1
->tree
, fnum
);
2257 smb_raw_exit(cli1
->session
);
2258 smb_raw_exit(cli2
->session
);
2259 smbcli_deltree(cli1
->tree
, BASEDIR
);
2263 static bool test_raw_oplock_batch18(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2265 const char *fname1
= BASEDIR
"\\test_batch18_1.dat";
2266 const char *fname2
= BASEDIR
"\\test_batch18_2.dat";
2270 union smb_rename rn
;
2273 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2278 smbcli_unlink(cli1
->tree
, fname1
);
2279 smbcli_unlink(cli1
->tree
, fname2
);
2281 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2284 base ntcreatex parms
2286 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2287 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2288 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2289 io
.ntcreatex
.in
.alloc_size
= 0;
2290 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2291 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2292 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2293 io
.ntcreatex
.in
.create_options
= 0;
2294 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2295 io
.ntcreatex
.in
.security_flags
= 0;
2296 io
.ntcreatex
.in
.fname
= fname1
;
2298 torture_comment(tctx
, "BATCH18: open a file with an batch oplock (share mode: none)\n");
2300 ZERO_STRUCT(break_info
);
2301 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2302 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2303 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2305 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2306 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2307 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2308 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2310 torture_comment(tctx
, "ntrename should trigger a break\n");
2312 rn
.generic
.level
= RAW_RENAME_NTRENAME
;
2313 rn
.ntrename
.in
.attrib
= 0;
2314 rn
.ntrename
.in
.flags
= RENAME_FLAG_RENAME
;
2315 rn
.ntrename
.in
.old_name
= fname1
;
2316 rn
.ntrename
.in
.new_name
= fname2
;
2317 torture_comment(tctx
, "trying rename while first file open\n");
2318 status
= smb_raw_rename(cli2
->tree
, &rn
);
2319 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
2321 torture_wait_for_oplock_break(tctx
);
2322 CHECK_VAL(break_info
.count
, 1);
2323 CHECK_VAL(break_info
.failures
, 0);
2324 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2326 smbcli_close(cli1
->tree
, fnum
);
2329 smb_raw_exit(cli1
->session
);
2330 smb_raw_exit(cli2
->session
);
2331 smbcli_deltree(cli1
->tree
, BASEDIR
);
2335 static bool test_raw_oplock_batch19(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2337 const char *fname1
= BASEDIR
"\\test_batch19_1.dat";
2338 const char *fname2
= BASEDIR
"\\test_batch19_2.dat";
2339 const char *fname3
= BASEDIR
"\\test_batch19_3.dat";
2343 union smb_fileinfo qfi
;
2344 union smb_setfileinfo sfi
;
2347 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2352 smbcli_unlink(cli1
->tree
, fname1
);
2353 smbcli_unlink(cli1
->tree
, fname2
);
2354 smbcli_unlink(cli1
->tree
, fname3
);
2356 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2359 base ntcreatex parms
2361 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2362 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2363 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2364 io
.ntcreatex
.in
.alloc_size
= 0;
2365 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2366 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2367 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
2368 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2369 io
.ntcreatex
.in
.create_options
= 0;
2370 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2371 io
.ntcreatex
.in
.security_flags
= 0;
2372 io
.ntcreatex
.in
.fname
= fname1
;
2374 torture_comment(tctx
, "BATCH19: open a file with an batch oplock (share mode: none)\n");
2375 ZERO_STRUCT(break_info
);
2376 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2377 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2378 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2379 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2380 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2381 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2382 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2384 torture_comment(tctx
, "setpathinfo rename info should trigger a break "
2387 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2388 sfi
.generic
.in
.file
.path
= fname1
;
2389 sfi
.rename_information
.in
.overwrite
= 0;
2390 sfi
.rename_information
.in
.root_fid
= 0;
2391 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2393 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
2394 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2396 torture_wait_for_oplock_break(tctx
);
2398 CHECK_VAL(break_info
.failures
, 0);
2400 if (TARGET_IS_WINXP(tctx
)) {
2401 /* Win XP breaks to level2. */
2402 CHECK_VAL(break_info
.count
, 1);
2403 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2404 } else if (TARGET_IS_W2K3(tctx
) || TARGET_IS_W2K8(tctx
) ||
2405 TARGET_IS_SAMBA3(tctx
) || TARGET_IS_SAMBA4(tctx
)) {
2406 /* Win2K3/2k8 incorrectly doesn't break at all. */
2407 CHECK_VAL(break_info
.count
, 0);
2409 /* win7/2k8r2 break to none. */
2410 CHECK_VAL(break_info
.count
, 1);
2411 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
2415 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2416 qfi
.generic
.in
.file
.fnum
= fnum
;
2418 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2419 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2420 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
2422 /* Close and re-open file with oplock. */
2423 smbcli_close(cli1
->tree
, fnum
);
2424 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2425 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2426 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2427 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2429 torture_comment(tctx
, "setfileinfo rename info on a client's own fid "
2430 "should not trigger a break nor a violation\n");
2431 ZERO_STRUCT(break_info
);
2433 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2434 sfi
.generic
.in
.file
.fnum
= fnum
;
2435 sfi
.rename_information
.in
.overwrite
= 0;
2436 sfi
.rename_information
.in
.root_fid
= 0;
2437 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
2439 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
2440 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2442 torture_wait_for_oplock_break(tctx
);
2443 if (TARGET_IS_WINXP(tctx
)) {
2444 /* XP incorrectly breaks to level2. */
2445 CHECK_VAL(break_info
.count
, 1);
2446 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2448 CHECK_VAL(break_info
.count
, 0);
2452 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2453 qfi
.generic
.in
.file
.fnum
= fnum
;
2455 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2456 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2457 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
2460 smbcli_close(cli1
->tree
, fnum
);
2461 smb_raw_exit(cli1
->session
);
2462 smb_raw_exit(cli2
->session
);
2463 smbcli_deltree(cli1
->tree
, BASEDIR
);
2467 /****************************************************
2468 Called from raw-rename - we need oplock handling for
2469 this test so this is why it's in oplock.c, not rename.c
2470 ****************************************************/
2472 bool test_trans2rename(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2474 const char *fname1
= BASEDIR
"\\test_trans2rename_1.dat";
2475 const char *fname2
= BASEDIR
"\\test_trans2rename_2.dat";
2476 const char *fname3
= BASEDIR
"\\test_trans2rename_3.dat";
2480 union smb_fileinfo qfi
;
2481 union smb_setfileinfo sfi
;
2484 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2489 smbcli_unlink(cli1
->tree
, fname1
);
2490 smbcli_unlink(cli1
->tree
, fname2
);
2491 smbcli_unlink(cli1
->tree
, fname3
);
2493 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2496 base ntcreatex parms
2498 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2499 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2500 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2501 io
.ntcreatex
.in
.alloc_size
= 0;
2502 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2503 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2504 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
2505 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2506 io
.ntcreatex
.in
.create_options
= 0;
2507 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2508 io
.ntcreatex
.in
.security_flags
= 0;
2509 io
.ntcreatex
.in
.fname
= fname1
;
2511 torture_comment(tctx
, "open a file with an exclusive oplock (share mode: none)\n");
2512 ZERO_STRUCT(break_info
);
2513 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2514 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
2515 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2516 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2517 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2518 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
2520 torture_comment(tctx
, "setpathinfo rename info should not trigger a break nor a violation\n");
2522 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2523 sfi
.generic
.in
.file
.path
= fname1
;
2524 sfi
.rename_information
.in
.overwrite
= 0;
2525 sfi
.rename_information
.in
.root_fid
= 0;
2526 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2528 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
2530 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2532 torture_wait_for_oplock_break(tctx
);
2533 CHECK_VAL(break_info
.count
, 0);
2536 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2537 qfi
.generic
.in
.file
.fnum
= fnum
;
2539 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2540 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2541 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
2543 torture_comment(tctx
, "setfileinfo rename info should not trigger a break nor a violation\n");
2545 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2546 sfi
.generic
.in
.file
.fnum
= fnum
;
2547 sfi
.rename_information
.in
.overwrite
= 0;
2548 sfi
.rename_information
.in
.root_fid
= 0;
2549 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
2551 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
2552 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2554 torture_wait_for_oplock_break(tctx
);
2555 CHECK_VAL(break_info
.count
, 0);
2558 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2559 qfi
.generic
.in
.file
.fnum
= fnum
;
2561 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2562 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2563 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
2566 smbcli_close(cli1
->tree
, fnum
);
2567 smb_raw_exit(cli1
->session
);
2568 smb_raw_exit(cli2
->session
);
2569 smbcli_deltree(cli1
->tree
, BASEDIR
);
2573 /****************************************************
2574 Called from raw-rename - we need oplock handling for
2575 this test so this is why it's in oplock.c, not rename.c
2576 ****************************************************/
2578 bool test_nttransrename(struct torture_context
*tctx
, struct smbcli_state
*cli1
)
2580 const char *fname1
= BASEDIR
"\\test_nttransrename_1.dat";
2581 const char *fname2
= BASEDIR
"\\test_nttransrename_2.dat";
2585 union smb_fileinfo qfi
, qpi
;
2586 union smb_rename rn
;
2589 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2594 smbcli_unlink(cli1
->tree
, fname1
);
2595 smbcli_unlink(cli1
->tree
, fname2
);
2597 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2600 base ntcreatex parms
2602 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2603 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2604 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2605 io
.ntcreatex
.in
.alloc_size
= 0;
2606 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2607 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2608 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2609 io
.ntcreatex
.in
.create_options
= 0;
2610 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2611 io
.ntcreatex
.in
.security_flags
= 0;
2612 io
.ntcreatex
.in
.fname
= fname1
;
2614 torture_comment(tctx
, "nttrans_rename: open a file with an exclusive oplock (share mode: none)\n");
2615 ZERO_STRUCT(break_info
);
2616 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2617 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
2618 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2619 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2620 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2621 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
2623 torture_comment(tctx
, "nttrans_rename: should not trigger a break nor a share mode violation\n");
2625 rn
.generic
.level
= RAW_RENAME_NTTRANS
;
2626 rn
.nttrans
.in
.file
.fnum
= fnum
;
2627 rn
.nttrans
.in
.flags
= 0;
2628 rn
.nttrans
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2630 status
= smb_raw_rename(cli1
->tree
, &rn
);
2631 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2633 torture_wait_for_oplock_break(tctx
);
2634 CHECK_VAL(break_info
.count
, 0);
2636 /* w2k3 does nothing, it doesn't rename the file */
2637 torture_comment(tctx
, "nttrans_rename: the server should have done nothing\n");
2639 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2640 qfi
.generic
.in
.file
.fnum
= fnum
;
2642 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2643 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2644 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname1
);
2647 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2648 qpi
.generic
.in
.file
.path
= fname1
;
2650 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
2651 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2652 CHECK_STRMATCH(qpi
.all_info
.out
.fname
.s
, fname1
);
2655 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2656 qpi
.generic
.in
.file
.path
= fname2
;
2658 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
2659 CHECK_STATUS(tctx
, status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
2661 torture_comment(tctx
, "nttrans_rename: after closing the file the file is still not renamed\n");
2662 status
= smbcli_close(cli1
->tree
, fnum
);
2663 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2666 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2667 qpi
.generic
.in
.file
.path
= fname1
;
2669 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
2670 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2671 CHECK_STRMATCH(qpi
.all_info
.out
.fname
.s
, fname1
);
2674 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2675 qpi
.generic
.in
.file
.path
= fname2
;
2677 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
2678 CHECK_STATUS(tctx
, status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
2680 torture_comment(tctx
, "nttrans_rename: rename with an invalid handle gives NT_STATUS_INVALID_HANDLE\n");
2682 rn
.generic
.level
= RAW_RENAME_NTTRANS
;
2683 rn
.nttrans
.in
.file
.fnum
= fnum
+1;
2684 rn
.nttrans
.in
.flags
= 0;
2685 rn
.nttrans
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2687 status
= smb_raw_rename(cli1
->tree
, &rn
);
2689 CHECK_STATUS(tctx
, status
, NT_STATUS_INVALID_HANDLE
);
2692 smb_raw_exit(cli1
->session
);
2693 smbcli_deltree(cli1
->tree
, BASEDIR
);
2698 static bool test_raw_oplock_batch20(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2700 const char *fname1
= BASEDIR
"\\test_batch20_1.dat";
2701 const char *fname2
= BASEDIR
"\\test_batch20_2.dat";
2702 const char *fname3
= BASEDIR
"\\test_batch20_3.dat";
2706 union smb_fileinfo qfi
;
2707 union smb_setfileinfo sfi
;
2708 uint16_t fnum
=0,fnum2
=0;
2710 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2715 smbcli_unlink(cli1
->tree
, fname1
);
2716 smbcli_unlink(cli1
->tree
, fname2
);
2717 smbcli_unlink(cli1
->tree
, fname3
);
2719 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2722 base ntcreatex parms
2724 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2725 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2726 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2727 io
.ntcreatex
.in
.alloc_size
= 0;
2728 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2729 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2730 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2731 io
.ntcreatex
.in
.create_options
= 0;
2732 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2733 io
.ntcreatex
.in
.security_flags
= 0;
2734 io
.ntcreatex
.in
.fname
= fname1
;
2736 torture_comment(tctx
, "BATCH20: open a file with an batch oplock (share mode: all)\n");
2737 ZERO_STRUCT(break_info
);
2738 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2739 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2740 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2741 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2742 NTCREATEX_SHARE_ACCESS_WRITE
|
2743 NTCREATEX_SHARE_ACCESS_DELETE
;
2744 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2745 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2746 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2747 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2750 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2751 sfi
.generic
.in
.file
.path
= fname1
;
2752 sfi
.rename_information
.in
.overwrite
= 0;
2753 sfi
.rename_information
.in
.root_fid
= 0;
2754 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2756 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
2757 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2759 torture_wait_for_oplock_break(tctx
);
2760 CHECK_VAL(break_info
.failures
, 0);
2762 if (TARGET_IS_WINXP(tctx
)) {
2763 /* Win XP breaks to level2. */
2764 CHECK_VAL(break_info
.count
, 1);
2765 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2766 } else if (TARGET_IS_W2K3(tctx
) || TARGET_IS_W2K8(tctx
) ||
2767 TARGET_IS_SAMBA3(tctx
) || TARGET_IS_SAMBA4(tctx
)) {
2768 /* Win2K3/2k8 incorrectly doesn't break at all. */
2769 CHECK_VAL(break_info
.count
, 0);
2771 /* win7/2k8r2 break to none. */
2772 CHECK_VAL(break_info
.count
, 1);
2773 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
2777 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2778 qfi
.generic
.in
.file
.fnum
= fnum
;
2780 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2781 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2782 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
2784 torture_comment(tctx
, "open a file with the new name an batch oplock (share mode: all)\n");
2785 ZERO_STRUCT(break_info
);
2786 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2787 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2788 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2789 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2790 NTCREATEX_SHARE_ACCESS_WRITE
|
2791 NTCREATEX_SHARE_ACCESS_DELETE
;
2792 io
.ntcreatex
.in
.fname
= fname2
;
2793 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
2794 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2795 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2796 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
2798 torture_wait_for_oplock_break(tctx
);
2800 if (TARGET_IS_WINXP(tctx
)) {
2801 /* XP broke to level2, and doesn't break again. */
2802 CHECK_VAL(break_info
.count
, 0);
2803 } else if (TARGET_IS_W2K3(tctx
) || TARGET_IS_W2K8(tctx
) ||
2804 TARGET_IS_SAMBA3(tctx
) || TARGET_IS_SAMBA4(tctx
)) {
2805 /* Win2K3 incorrectly didn't break before so break now. */
2806 CHECK_VAL(break_info
.count
, 1);
2807 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2809 /* win7/2k8r2 broke to none, and doesn't break again. */
2810 CHECK_VAL(break_info
.count
, 0);
2813 ZERO_STRUCT(break_info
);
2816 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2817 sfi
.generic
.in
.file
.fnum
= fnum
;
2818 sfi
.rename_information
.in
.overwrite
= 0;
2819 sfi
.rename_information
.in
.root_fid
= 0;
2820 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
2822 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
2823 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2825 torture_wait_for_oplock_break(tctx
);
2826 CHECK_VAL(break_info
.count
, 0);
2829 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2830 qfi
.generic
.in
.file
.fnum
= fnum
;
2832 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2833 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2834 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
2837 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2838 qfi
.generic
.in
.file
.fnum
= fnum2
;
2840 status
= smb_raw_fileinfo(cli2
->tree
, tctx
, &qfi
);
2841 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2842 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
2846 smbcli_close(cli1
->tree
, fnum
);
2847 smbcli_close(cli2
->tree
, fnum2
);
2848 smb_raw_exit(cli1
->session
);
2849 smb_raw_exit(cli2
->session
);
2850 smbcli_deltree(cli1
->tree
, BASEDIR
);
2854 static bool test_raw_oplock_batch21(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2856 const char *fname
= BASEDIR
"\\test_batch21.dat";
2865 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2870 smbcli_unlink(cli1
->tree
, fname
);
2872 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2875 base ntcreatex parms
2877 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2878 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2879 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2880 io
.ntcreatex
.in
.alloc_size
= 0;
2881 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2882 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2883 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2884 io
.ntcreatex
.in
.create_options
= 0;
2885 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2886 io
.ntcreatex
.in
.security_flags
= 0;
2887 io
.ntcreatex
.in
.fname
= fname
;
2890 with a batch oplock we get a break
2892 torture_comment(tctx
, "BATCH21: open with batch oplock\n");
2893 ZERO_STRUCT(break_info
);
2894 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2895 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2896 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2897 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2898 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2899 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2900 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2902 torture_comment(tctx
, "writing should not generate a break\n");
2903 wr
= smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
2905 CHECK_STATUS(tctx
, smbcli_nt_error(cli1
->tree
), NT_STATUS_OK
);
2908 e
.in
.repeat_count
= 1;
2909 status
= smb_raw_echo(cli1
->transport
, &e
);
2910 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2912 torture_wait_for_oplock_break(tctx
);
2913 CHECK_VAL(break_info
.count
, 0);
2915 smbcli_close(cli1
->tree
, fnum
);
2918 smb_raw_exit(cli1
->session
);
2919 smb_raw_exit(cli2
->session
);
2920 smbcli_deltree(cli1
->tree
, BASEDIR
);
2924 static bool test_raw_oplock_batch22(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2926 const char *fname
= BASEDIR
"\\test_batch22.dat";
2930 uint16_t fnum
= 0, fnum2
= 0, fnum3
= 0;
2932 int timeout
= torture_setting_int(tctx
, "oplocktimeout", 30);
2935 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2940 smbcli_unlink(cli1
->tree
, fname
);
2942 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2944 base ntcreatex parms
2946 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2947 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2948 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2949 io
.ntcreatex
.in
.alloc_size
= 0;
2950 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2951 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2952 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2953 io
.ntcreatex
.in
.create_options
= 0;
2954 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2955 io
.ntcreatex
.in
.security_flags
= 0;
2956 io
.ntcreatex
.in
.fname
= fname
;
2959 with a batch oplock we get a break
2961 torture_comment(tctx
, "BATCH22: open with batch oplock\n");
2962 ZERO_STRUCT(break_info
);
2963 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2964 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2965 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2966 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2967 NTCREATEX_SHARE_ACCESS_WRITE
|
2968 NTCREATEX_SHARE_ACCESS_DELETE
;
2969 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2970 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2971 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2972 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2974 torture_comment(tctx
, "a 2nd open should not succeed after the oplock "
2976 tv
= timeval_current();
2977 smbcli_oplock_handler(cli1
->transport
, oplock_handler_timeout
, cli1
->tree
);
2978 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2980 if (TARGET_IS_W2K3(tctx
)) {
2981 /* 2k3 has an issue here. xp/win7 are ok. */
2982 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
2984 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2987 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2989 torture_wait_for_oplock_break(tctx
);
2990 te
= (int)timeval_elapsed(&tv
);
2993 * Some servers detect clients that let oplocks timeout, so this check
2994 * only shows a warning message instead failing the test to eliminate
2995 * failures from repeated runs of the test. This isn't ideal, but
2996 * it's better than not running the test at all.
2998 CHECK_RANGE(te
, timeout
- 1, timeout
+ 15);
3000 CHECK_VAL(break_info
.count
, 1);
3001 CHECK_VAL(break_info
.fnum
, fnum
);
3002 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3003 CHECK_VAL(break_info
.failures
, 0);
3004 ZERO_STRUCT(break_info
);
3006 torture_comment(tctx
, "a 2nd open should succeed after the oplock "
3007 "release without break\n");
3008 tv
= timeval_current();
3009 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3010 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3011 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3013 /* Samba 3.6.0 and above behave as Windows. */
3014 if (TARGET_IS_SAMBA3(tctx
)) {
3015 /* samba3 doesn't grant additional oplocks to bad clients. */
3016 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
3018 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3019 LEVEL_II_OPLOCK_RETURN
);
3022 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3023 LEVEL_II_OPLOCK_RETURN
);
3025 torture_wait_for_oplock_break(tctx
);
3026 te
= (int)timeval_elapsed(&tv
);
3027 /* it should come in without delay */
3028 CHECK_RANGE(te
+1, 0, timeout
);
3029 fnum3
= io
.ntcreatex
.out
.file
.fnum
;
3031 CHECK_VAL(break_info
.count
, 0);
3033 smbcli_close(cli1
->tree
, fnum
);
3034 smbcli_close(cli1
->tree
, fnum2
);
3035 smbcli_close(cli1
->tree
, fnum3
);
3038 smb_raw_exit(cli1
->session
);
3039 smb_raw_exit(cli2
->session
);
3040 smbcli_deltree(cli1
->tree
, BASEDIR
);
3044 static bool test_raw_oplock_batch23(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
3046 const char *fname
= BASEDIR
"\\test_batch23.dat";
3050 uint16_t fnum
=0, fnum2
=0,fnum3
=0;
3051 struct smbcli_state
*cli3
= NULL
;
3053 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3058 smbcli_unlink(cli1
->tree
, fname
);
3060 ret
= open_connection_no_level2_oplocks(tctx
, &cli3
);
3061 CHECK_VAL(ret
, true);
3063 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3064 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
3065 smbcli_oplock_handler(cli3
->transport
, oplock_handler_ack_to_given
, cli3
->tree
);
3068 base ntcreatex parms
3070 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3071 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3072 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3073 io
.ntcreatex
.in
.alloc_size
= 0;
3074 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3075 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3076 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3077 io
.ntcreatex
.in
.create_options
= 0;
3078 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3079 io
.ntcreatex
.in
.security_flags
= 0;
3080 io
.ntcreatex
.in
.fname
= fname
;
3082 torture_comment(tctx
, "BATCH23: a open and ask for a batch oplock\n");
3083 ZERO_STRUCT(break_info
);
3085 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
| SEC_RIGHTS_FILE_WRITE
;
3086 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
3087 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3088 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3089 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3090 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3091 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3092 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3093 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3095 ZERO_STRUCT(break_info
);
3097 torture_comment(tctx
, "a 2nd open without level2 oplock support should generate a break to level2\n");
3098 status
= smb_raw_open(cli3
->tree
, tctx
, &io
);
3099 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3100 fnum3
= io
.ntcreatex
.out
.file
.fnum
;
3101 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
3103 torture_wait_for_oplock_break(tctx
);
3104 CHECK_VAL(break_info
.count
, 1);
3105 CHECK_VAL(break_info
.fnum
, fnum
);
3106 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3107 CHECK_VAL(break_info
.failures
, 0);
3109 ZERO_STRUCT(break_info
);
3111 torture_comment(tctx
, "a 3rd open with level2 oplock support should not generate a break\n");
3112 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3113 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3114 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3115 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
3117 torture_wait_for_oplock_break(tctx
);
3118 CHECK_VAL(break_info
.count
, 0);
3120 smbcli_close(cli1
->tree
, fnum
);
3121 smbcli_close(cli2
->tree
, fnum2
);
3122 smbcli_close(cli3
->tree
, fnum3
);
3125 smb_raw_exit(cli1
->session
);
3126 smb_raw_exit(cli2
->session
);
3127 smb_raw_exit(cli3
->session
);
3128 smbcli_deltree(cli1
->tree
, BASEDIR
);
3132 static bool test_raw_oplock_batch24(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
3134 const char *fname
= BASEDIR
"\\test_batch24.dat";
3138 uint16_t fnum2
=0,fnum3
=0;
3139 struct smbcli_state
*cli3
= NULL
;
3141 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3146 smbcli_unlink(cli1
->tree
, fname
);
3148 ret
= open_connection_no_level2_oplocks(tctx
, &cli3
);
3149 CHECK_VAL(ret
, true);
3151 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3152 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
3153 smbcli_oplock_handler(cli3
->transport
, oplock_handler_ack_to_given
, cli3
->tree
);
3156 base ntcreatex parms
3158 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3159 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3160 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3161 io
.ntcreatex
.in
.alloc_size
= 0;
3162 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3163 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3164 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3165 io
.ntcreatex
.in
.create_options
= 0;
3166 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3167 io
.ntcreatex
.in
.security_flags
= 0;
3168 io
.ntcreatex
.in
.fname
= fname
;
3170 torture_comment(tctx
, "BATCH24: a open without level support and ask for a batch oplock\n");
3171 ZERO_STRUCT(break_info
);
3173 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
| SEC_RIGHTS_FILE_WRITE
;
3174 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
3175 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3176 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3177 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3178 status
= smb_raw_open(cli3
->tree
, tctx
, &io
);
3179 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3180 fnum3
= io
.ntcreatex
.out
.file
.fnum
;
3181 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3183 ZERO_STRUCT(break_info
);
3185 torture_comment(tctx
, "a 2nd open with level2 oplock support should generate a break to none\n");
3186 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3187 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3188 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3189 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
3191 torture_wait_for_oplock_break(tctx
);
3192 CHECK_VAL(break_info
.count
, 1);
3193 CHECK_VAL(break_info
.fnum
, fnum3
);
3194 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
3195 CHECK_VAL(break_info
.failures
, 0);
3197 smbcli_close(cli3
->tree
, fnum3
);
3198 smbcli_close(cli2
->tree
, fnum2
);
3201 smb_raw_exit(cli1
->session
);
3202 smb_raw_exit(cli2
->session
);
3203 smb_raw_exit(cli3
->session
);
3204 smbcli_deltree(cli1
->tree
, BASEDIR
);
3208 static bool test_raw_oplock_batch25(struct torture_context
*tctx
,
3209 struct smbcli_state
*cli1
,
3210 struct smbcli_state
*cli2
)
3212 const char *fname
= BASEDIR
"\\test_batch25.dat";
3216 union smb_setfileinfo sfi
;
3219 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3224 smbcli_unlink(cli1
->tree
, fname
);
3226 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3229 base ntcreatex parms
3231 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3232 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3233 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3234 io
.ntcreatex
.in
.alloc_size
= 0;
3235 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3236 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3237 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3238 io
.ntcreatex
.in
.create_options
= 0;
3239 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3240 io
.ntcreatex
.in
.security_flags
= 0;
3241 io
.ntcreatex
.in
.fname
= fname
;
3243 torture_comment(tctx
, "BATCH25: open a file with an batch oplock "
3244 "(share mode: none)\n");
3246 ZERO_STRUCT(break_info
);
3247 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3248 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3249 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3250 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3251 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3252 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3253 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3255 torture_comment(tctx
, "setpathinfo attribute info should not trigger "
3256 "a break nor a violation\n");
3258 sfi
.generic
.level
= RAW_SFILEINFO_SETATTR
;
3259 sfi
.generic
.in
.file
.path
= fname
;
3260 sfi
.setattr
.in
.attrib
= FILE_ATTRIBUTE_HIDDEN
;
3261 sfi
.setattr
.in
.write_time
= 0;
3263 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
3264 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3266 torture_wait_for_oplock_break(tctx
);
3267 CHECK_VAL(break_info
.count
, 0);
3269 smbcli_close(cli1
->tree
, fnum
);
3272 smb_raw_exit(cli1
->session
);
3273 smb_raw_exit(cli2
->session
);
3274 smbcli_deltree(cli1
->tree
, BASEDIR
);
3279 * Similar to batch17/18, but test with open share mode rather than
3282 static bool test_raw_oplock_batch26(struct torture_context
*tctx
,
3283 struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
3285 const char *fname1
= BASEDIR
"\\test_batch26_1.dat";
3286 const char *fname2
= BASEDIR
"\\test_batch26_2.dat";
3290 union smb_rename rn
;
3293 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3298 smbcli_unlink(cli1
->tree
, fname1
);
3299 smbcli_unlink(cli1
->tree
, fname2
);
3301 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
3305 base ntcreatex parms
3307 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3308 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3309 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3310 io
.ntcreatex
.in
.alloc_size
= 0;
3311 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3312 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3313 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
3314 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3315 io
.ntcreatex
.in
.create_options
= 0;
3316 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3317 io
.ntcreatex
.in
.security_flags
= 0;
3318 io
.ntcreatex
.in
.fname
= fname1
;
3320 torture_comment(tctx
, "BATCH26: open a file with an batch oplock "
3321 "(share mode: none)\n");
3323 ZERO_STRUCT(break_info
);
3324 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3325 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3326 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3329 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3330 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3331 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3332 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3334 torture_comment(tctx
, "rename should trigger a break\n");
3336 rn
.generic
.level
= RAW_RENAME_RENAME
;
3337 rn
.rename
.in
.pattern1
= fname1
;
3338 rn
.rename
.in
.pattern2
= fname2
;
3339 rn
.rename
.in
.attrib
= 0;
3341 torture_comment(tctx
, "trying rename while first file open\n");
3342 status
= smb_raw_rename(cli2
->tree
, &rn
);
3343 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
3345 torture_wait_for_oplock_break(tctx
);
3346 CHECK_VAL(break_info
.count
, 1);
3347 CHECK_VAL(break_info
.failures
, 0);
3348 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3350 /* Close and reopen with batch again. */
3351 smbcli_close(cli1
->tree
, fnum
);
3352 ZERO_STRUCT(break_info
);
3354 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3355 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3356 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3357 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3359 /* Now try ntrename. */
3360 torture_comment(tctx
, "ntrename should trigger a break\n");
3362 rn
.generic
.level
= RAW_RENAME_NTRENAME
;
3363 rn
.ntrename
.in
.attrib
= 0;
3364 rn
.ntrename
.in
.flags
= RENAME_FLAG_RENAME
;
3365 rn
.ntrename
.in
.old_name
= fname1
;
3366 rn
.ntrename
.in
.new_name
= fname2
;
3367 torture_comment(tctx
, "trying rename while first file open\n");
3368 status
= smb_raw_rename(cli2
->tree
, &rn
);
3369 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
3371 torture_wait_for_oplock_break(tctx
);
3372 CHECK_VAL(break_info
.count
, 1);
3373 CHECK_VAL(break_info
.failures
, 0);
3374 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3376 smbcli_close(cli1
->tree
, fnum
);
3379 smb_raw_exit(cli1
->session
);
3380 smb_raw_exit(cli2
->session
);
3381 smbcli_deltree(cli1
->tree
, BASEDIR
);
3385 /* Test how oplocks work on streams. */
3386 static bool test_raw_oplock_stream1(struct torture_context
*tctx
,
3387 struct smbcli_state
*cli1
,
3388 struct smbcli_state
*cli2
)
3392 const char *fname_base
= BASEDIR
"\\test_stream1.txt";
3393 const char *stream
= "Stream One:$DATA";
3394 const char *fname_stream
, *fname_default_stream
;
3395 const char *default_stream
= "::$DATA";
3399 int stream_fnum
= -1;
3400 uint32_t batch_req
= NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3401 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
| NTCREATEX_FLAGS_EXTENDED
;
3402 uint32_t exclusive_req
= NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3403 NTCREATEX_FLAGS_EXTENDED
;
3405 #define NSTREAM_OPLOCK_RESULTS 8
3408 bool open_base_file
;
3409 uint32_t oplock_req
;
3410 uint32_t oplock_granted
;
3411 } stream_oplock_results
[NSTREAM_OPLOCK_RESULTS
] = {
3412 /* Request oplock on stream without the base file open. */
3413 {&fname_stream
, false, batch_req
, NO_OPLOCK_RETURN
},
3414 {&fname_default_stream
, false, batch_req
, NO_OPLOCK_RETURN
},
3415 {&fname_stream
, false, exclusive_req
, EXCLUSIVE_OPLOCK_RETURN
},
3416 {&fname_default_stream
, false, exclusive_req
, EXCLUSIVE_OPLOCK_RETURN
},
3418 /* Request oplock on stream with the base file open. */
3419 {&fname_stream
, true, batch_req
, NO_OPLOCK_RETURN
},
3420 {&fname_default_stream
, true, batch_req
, NO_OPLOCK_RETURN
},
3421 {&fname_stream
, true, exclusive_req
, EXCLUSIVE_OPLOCK_RETURN
},
3422 {&fname_default_stream
, true, exclusive_req
, LEVEL_II_OPLOCK_RETURN
},
3427 /* Only passes against windows at the moment. */
3428 if (torture_setting_bool(tctx
, "samba3", false) ||
3429 torture_setting_bool(tctx
, "samba4", false)) {
3430 torture_skip(tctx
, "STREAM1 disabled against samba3+4\n");
3433 fname_stream
= talloc_asprintf(tctx
, "%s:%s", fname_base
, stream
);
3434 fname_default_stream
= talloc_asprintf(tctx
, "%s%s", fname_base
,
3437 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3440 smbcli_unlink(cli1
->tree
, fname_base
);
3442 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3443 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
3445 /* Setup generic open parameters. */
3446 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3447 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3448 io
.ntcreatex
.in
.access_mask
= (SEC_FILE_READ_DATA
|SEC_FILE_WRITE_DATA
|
3449 SEC_FILE_APPEND_DATA
|SEC_STD_READ_CONTROL
);
3450 io
.ntcreatex
.in
.create_options
= 0;
3451 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3452 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3453 NTCREATEX_SHARE_ACCESS_WRITE
;
3454 io
.ntcreatex
.in
.alloc_size
= 0;
3455 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3456 io
.ntcreatex
.in
.security_flags
= 0;
3458 /* Create the file with a stream */
3459 io
.ntcreatex
.in
.fname
= fname_stream
;
3460 io
.ntcreatex
.in
.flags
= 0;
3461 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
3462 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3463 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3464 smbcli_close(cli1
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3466 /* Change the disposition to open now that the file has been created. */
3467 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
3469 /* Try some permutations of taking oplocks on streams. */
3470 for (i
= 0; i
< NSTREAM_OPLOCK_RESULTS
; i
++) {
3471 const char *fname
= *stream_oplock_results
[i
].fname
;
3472 bool open_base_file
= stream_oplock_results
[i
].open_base_file
;
3473 uint32_t oplock_req
= stream_oplock_results
[i
].oplock_req
;
3474 uint32_t oplock_granted
=
3475 stream_oplock_results
[i
].oplock_granted
;
3478 if (open_base_file
) {
3479 torture_comment(tctx
, "Opening base file: %s with "
3480 "%d\n", fname_base
, batch_req
);
3481 io
.ntcreatex
.in
.fname
= fname_base
;
3482 io
.ntcreatex
.in
.flags
= batch_req
;
3483 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3484 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3485 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3486 BATCH_OPLOCK_RETURN
);
3487 base_fnum
= io
.ntcreatex
.out
.file
.fnum
;
3490 torture_comment(tctx
, "%d: Opening stream: %s with %d\n", i
,
3492 io
.ntcreatex
.in
.fname
= fname
;
3493 io
.ntcreatex
.in
.flags
= oplock_req
;
3495 /* Do the open with the desired oplock on the stream. */
3496 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3497 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3498 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, oplock_granted
);
3499 smbcli_close(cli1
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3501 /* Cleanup the base file if it was opened. */
3502 if (base_fnum
!= -1) {
3503 smbcli_close(cli2
->tree
, base_fnum
);
3507 /* Open the stream with an exclusive oplock. */
3508 torture_comment(tctx
, "Opening stream: %s with %d\n",
3509 fname_stream
, exclusive_req
);
3510 io
.ntcreatex
.in
.fname
= fname_stream
;
3511 io
.ntcreatex
.in
.flags
= exclusive_req
;
3512 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3513 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3514 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
3515 stream_fnum
= io
.ntcreatex
.out
.file
.fnum
;
3517 /* Open the base file and see if it contends. */
3518 ZERO_STRUCT(break_info
);
3519 torture_comment(tctx
, "Opening base file: %s with "
3520 "%d\n", fname_base
, batch_req
);
3521 io
.ntcreatex
.in
.fname
= fname_base
;
3522 io
.ntcreatex
.in
.flags
= batch_req
;
3523 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3524 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3525 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3526 BATCH_OPLOCK_RETURN
);
3527 smbcli_close(cli2
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3529 torture_wait_for_oplock_break(tctx
);
3530 CHECK_VAL(break_info
.count
, 0);
3531 CHECK_VAL(break_info
.failures
, 0);
3533 /* Open the stream again to see if it contends. */
3534 ZERO_STRUCT(break_info
);
3535 torture_comment(tctx
, "Opening stream again: %s with "
3536 "%d\n", fname_base
, batch_req
);
3537 io
.ntcreatex
.in
.fname
= fname_stream
;
3538 io
.ntcreatex
.in
.flags
= exclusive_req
;
3539 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3540 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3541 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3542 LEVEL_II_OPLOCK_RETURN
);
3543 smbcli_close(cli2
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3545 torture_wait_for_oplock_break(tctx
);
3546 CHECK_VAL(break_info
.count
, 1);
3547 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3548 CHECK_VAL(break_info
.failures
, 0);
3550 /* Close the stream. */
3551 if (stream_fnum
!= -1) {
3552 smbcli_close(cli1
->tree
, stream_fnum
);
3556 smbcli_close(cli1
->tree
, fnum
);
3557 smb_raw_exit(cli1
->session
);
3558 smb_raw_exit(cli2
->session
);
3559 smbcli_deltree(cli1
->tree
, BASEDIR
);
3563 static bool test_raw_oplock_doc(struct torture_context
*tctx
,
3564 struct smbcli_state
*cli
)
3566 const char *fname
= BASEDIR
"\\test_oplock_doc.dat";
3572 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
3575 smbcli_unlink(cli
->tree
, fname
);
3577 smbcli_oplock_handler(cli
->transport
, oplock_handler_ack_to_given
,
3581 base ntcreatex parms
3583 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3584 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3585 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3586 io
.ntcreatex
.in
.alloc_size
= 0;
3587 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3588 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3589 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3590 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DELETE_ON_CLOSE
;
3591 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3592 io
.ntcreatex
.in
.security_flags
= 0;
3593 io
.ntcreatex
.in
.fname
= fname
;
3595 torture_comment(tctx
, "open a delete-on-close file with a batch "
3597 ZERO_STRUCT(break_info
);
3598 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3599 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3600 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3602 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
3603 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3604 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3605 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3607 smbcli_close(cli
->tree
, fnum
);
3610 smb_raw_exit(cli
->session
);
3611 smbcli_deltree(cli
->tree
, BASEDIR
);
3615 /* Open a file with a batch oplock, then open it again from a second client
3616 * requesting no oplock. Having two open file handles should break our own
3617 * oplock during BRL acquisition.
3619 static bool test_raw_oplock_brl1(struct torture_context
*tctx
,
3620 struct smbcli_state
*cli1
,
3621 struct smbcli_state
*cli2
)
3623 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
3632 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3637 smbcli_unlink(cli1
->tree
, fname
);
3639 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
3643 base ntcreatex parms
3645 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3646 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3647 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
3648 SEC_RIGHTS_FILE_WRITE
;
3649 io
.ntcreatex
.in
.alloc_size
= 0;
3650 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3651 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3652 NTCREATEX_SHARE_ACCESS_WRITE
;
3653 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3654 io
.ntcreatex
.in
.create_options
= 0;
3655 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3656 io
.ntcreatex
.in
.security_flags
= 0;
3657 io
.ntcreatex
.in
.fname
= fname
;
3660 with a batch oplock we get a break
3662 torture_comment(tctx
, "open with batch oplock\n");
3663 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3664 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3665 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3667 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3668 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3669 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3670 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3671 /* create a file with bogus data */
3672 memset(buf
, 0, sizeof(buf
));
3674 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
3677 torture_comment(tctx
, "Failed to create file\n");
3681 torture_comment(tctx
, "a 2nd open should give a break\n");
3682 ZERO_STRUCT(break_info
);
3684 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
3685 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3686 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3687 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3688 CHECK_VAL(break_info
.count
, 1);
3689 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3690 CHECK_VAL(break_info
.failures
, 0);
3691 CHECK_VAL(break_info
.fnum
, fnum
);
3693 ZERO_STRUCT(break_info
);
3695 torture_comment(tctx
, "a self BRL acquisition should break to none\n");
3697 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 4, 0, WRITE_LOCK
);
3698 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3700 torture_wait_for_oplock_break(tctx
);
3701 CHECK_VAL(break_info
.count
, 1);
3702 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
3703 CHECK_VAL(break_info
.fnum
, fnum
);
3704 CHECK_VAL(break_info
.failures
, 0);
3706 /* expect no oplock break */
3707 ZERO_STRUCT(break_info
);
3708 status
= smbcli_lock(cli1
->tree
, fnum
, 2, 4, 0, WRITE_LOCK
);
3709 CHECK_STATUS(tctx
, status
, NT_STATUS_LOCK_NOT_GRANTED
);
3711 torture_wait_for_oplock_break(tctx
);
3712 CHECK_VAL(break_info
.count
, 0);
3713 CHECK_VAL(break_info
.level
, 0);
3714 CHECK_VAL(break_info
.fnum
, 0);
3715 CHECK_VAL(break_info
.failures
, 0);
3717 smbcli_close(cli1
->tree
, fnum
);
3718 smbcli_close(cli2
->tree
, fnum2
);
3721 smb_raw_exit(cli1
->session
);
3722 smb_raw_exit(cli2
->session
);
3723 smbcli_deltree(cli1
->tree
, BASEDIR
);
3728 /* Open a file with a batch oplock on one client and then acquire a brl.
3729 * We should not contend our own oplock.
3731 static bool test_raw_oplock_brl2(struct torture_context
*tctx
, struct smbcli_state
*cli1
)
3733 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
3741 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3746 smbcli_unlink(cli1
->tree
, fname
);
3748 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
3752 base ntcreatex parms
3754 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3755 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3756 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
3757 SEC_RIGHTS_FILE_WRITE
;
3758 io
.ntcreatex
.in
.alloc_size
= 0;
3759 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3760 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3761 NTCREATEX_SHARE_ACCESS_WRITE
;
3762 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3763 io
.ntcreatex
.in
.create_options
= 0;
3764 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3765 io
.ntcreatex
.in
.security_flags
= 0;
3766 io
.ntcreatex
.in
.fname
= fname
;
3769 with a batch oplock we get a break
3771 torture_comment(tctx
, "open with batch oplock\n");
3772 ZERO_STRUCT(break_info
);
3773 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3774 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3775 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3777 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3778 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3779 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3780 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3782 /* create a file with bogus data */
3783 memset(buf
, 0, sizeof(buf
));
3785 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
3788 torture_comment(tctx
, "Failed to create file\n");
3792 torture_comment(tctx
, "a self BRL acquisition should not break to "
3795 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 4, 0, WRITE_LOCK
);
3796 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3798 status
= smbcli_lock(cli1
->tree
, fnum
, 2, 4, 0, WRITE_LOCK
);
3799 CHECK_STATUS(tctx
, status
, NT_STATUS_LOCK_NOT_GRANTED
);
3801 /* With one file handle open a BRL should not contend our oplock.
3802 * Thus, no oplock break will be received and the entire break_info
3803 * struct will be 0 */
3804 torture_wait_for_oplock_break(tctx
);
3805 CHECK_VAL(break_info
.fnum
, 0);
3806 CHECK_VAL(break_info
.count
, 0);
3807 CHECK_VAL(break_info
.level
, 0);
3808 CHECK_VAL(break_info
.failures
, 0);
3810 smbcli_close(cli1
->tree
, fnum
);
3813 smb_raw_exit(cli1
->session
);
3814 smbcli_deltree(cli1
->tree
, BASEDIR
);
3818 /* Open a file with a batch oplock twice from one client and then acquire a
3819 * brl. BRL acquisition should break our own oplock.
3821 static bool test_raw_oplock_brl3(struct torture_context
*tctx
,
3822 struct smbcli_state
*cli1
)
3824 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
3832 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3837 smbcli_unlink(cli1
->tree
, fname
);
3839 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
3843 base ntcreatex parms
3845 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3846 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3847 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
3848 SEC_RIGHTS_FILE_WRITE
;
3849 io
.ntcreatex
.in
.alloc_size
= 0;
3850 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3851 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3852 NTCREATEX_SHARE_ACCESS_WRITE
;
3853 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3854 io
.ntcreatex
.in
.create_options
= 0;
3855 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3856 io
.ntcreatex
.in
.security_flags
= 0;
3857 io
.ntcreatex
.in
.fname
= fname
;
3860 with a batch oplock we get a break
3862 torture_comment(tctx
, "open with batch oplock\n");
3863 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3864 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3865 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3867 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3868 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3869 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3870 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3872 /* create a file with bogus data */
3873 memset(buf
, 0, sizeof(buf
));
3875 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
3878 torture_comment(tctx
, "Failed to create file\n");
3883 torture_comment(tctx
, "a 2nd open should give a break\n");
3884 ZERO_STRUCT(break_info
);
3886 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
3887 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3888 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3889 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3890 CHECK_VAL(break_info
.count
, 1);
3891 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3892 CHECK_VAL(break_info
.failures
, 0);
3893 CHECK_VAL(break_info
.fnum
, fnum
);
3895 ZERO_STRUCT(break_info
);
3897 torture_comment(tctx
, "a self BRL acquisition should break to none\n");
3899 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 4, 0, WRITE_LOCK
);
3900 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3902 torture_wait_for_oplock_break(tctx
);
3903 CHECK_VAL(break_info
.count
, 1);
3904 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
3905 CHECK_VAL(break_info
.fnum
, fnum
);
3906 CHECK_VAL(break_info
.failures
, 0);
3908 /* expect no oplock break */
3909 ZERO_STRUCT(break_info
);
3910 status
= smbcli_lock(cli1
->tree
, fnum
, 2, 4, 0, WRITE_LOCK
);
3911 CHECK_STATUS(tctx
, status
, NT_STATUS_LOCK_NOT_GRANTED
);
3913 torture_wait_for_oplock_break(tctx
);
3914 CHECK_VAL(break_info
.count
, 0);
3915 CHECK_VAL(break_info
.level
, 0);
3916 CHECK_VAL(break_info
.fnum
, 0);
3917 CHECK_VAL(break_info
.failures
, 0);
3919 smbcli_close(cli1
->tree
, fnum
);
3920 smbcli_close(cli1
->tree
, fnum2
);
3923 smb_raw_exit(cli1
->session
);
3924 smbcli_deltree(cli1
->tree
, BASEDIR
);
3929 * Open a file with an exclusive oplock from the 1st client and acquire a
3930 * brl. Then open the same file from the 2nd client that should give oplock
3931 * break with level2 to the 1st and return no oplock to the 2nd.
3933 static bool test_raw_oplock_brl4(struct torture_context
*tctx
,
3934 struct smbcli_state
*cli1
,
3935 struct smbcli_state
*cli2
)
3937 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
3945 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3950 smbcli_unlink(cli1
->tree
, fname
);
3952 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
3956 base ntcreatex parms
3958 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3959 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3960 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
3961 SEC_RIGHTS_FILE_WRITE
;
3962 io
.ntcreatex
.in
.alloc_size
= 0;
3963 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3964 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3965 NTCREATEX_SHARE_ACCESS_WRITE
;
3966 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3967 io
.ntcreatex
.in
.create_options
= 0;
3968 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3969 io
.ntcreatex
.in
.security_flags
= 0;
3970 io
.ntcreatex
.in
.fname
= fname
;
3972 torture_comment(tctx
, "open with exclusive oplock\n");
3973 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3974 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
3976 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3978 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3979 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3980 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
3982 /* create a file with bogus data */
3983 memset(buf
, 0, sizeof(buf
));
3985 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
3988 torture_comment(tctx
, "Failed to create file\n");
3992 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 1, 0, WRITE_LOCK
);
3993 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3995 torture_comment(tctx
, "a 2nd open should give a break to the 1st\n");
3996 ZERO_STRUCT(break_info
);
3998 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
4000 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4001 CHECK_VAL(break_info
.count
, 1);
4002 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
4003 CHECK_VAL(break_info
.failures
, 0);
4004 CHECK_VAL(break_info
.fnum
, fnum
);
4006 torture_comment(tctx
, "and return no oplock to the 2nd\n");
4007 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
4008 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
4010 smbcli_close(cli1
->tree
, fnum
);
4011 smbcli_close(cli2
->tree
, fnum2
);
4014 smb_raw_exit(cli1
->session
);
4015 smb_raw_exit(cli2
->session
);
4016 smbcli_deltree(cli1
->tree
, BASEDIR
);
4021 basic testing of oplocks
4023 struct torture_suite
*torture_raw_oplock(TALLOC_CTX
*mem_ctx
)
4025 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "oplock");
4027 torture_suite_add_2smb_test(suite
, "exclusive1", test_raw_oplock_exclusive1
);
4028 torture_suite_add_2smb_test(suite
, "exclusive2", test_raw_oplock_exclusive2
);
4029 torture_suite_add_2smb_test(suite
, "exclusive3", test_raw_oplock_exclusive3
);
4030 torture_suite_add_2smb_test(suite
, "exclusive4", test_raw_oplock_exclusive4
);
4031 torture_suite_add_2smb_test(suite
, "exclusive5", test_raw_oplock_exclusive5
);
4032 torture_suite_add_2smb_test(suite
, "exclusive6", test_raw_oplock_exclusive6
);
4033 torture_suite_add_2smb_test(suite
, "exclusive7", test_raw_oplock_exclusive7
);
4034 torture_suite_add_2smb_test(suite
, "exclusive8",
4035 test_raw_oplock_exclusive8
);
4036 torture_suite_add_2smb_test(suite
, "batch1", test_raw_oplock_batch1
);
4037 torture_suite_add_2smb_test(suite
, "batch2", test_raw_oplock_batch2
);
4038 torture_suite_add_2smb_test(suite
, "batch3", test_raw_oplock_batch3
);
4039 torture_suite_add_2smb_test(suite
, "batch4", test_raw_oplock_batch4
);
4040 torture_suite_add_2smb_test(suite
, "batch5", test_raw_oplock_batch5
);
4041 torture_suite_add_2smb_test(suite
, "batch6", test_raw_oplock_batch6
);
4042 torture_suite_add_2smb_test(suite
, "batch7", test_raw_oplock_batch7
);
4043 torture_suite_add_2smb_test(suite
, "batch8", test_raw_oplock_batch8
);
4044 torture_suite_add_2smb_test(suite
, "batch9", test_raw_oplock_batch9
);
4045 torture_suite_add_2smb_test(suite
, "batch10", test_raw_oplock_batch10
);
4046 torture_suite_add_2smb_test(suite
, "batch11", test_raw_oplock_batch11
);
4047 torture_suite_add_2smb_test(suite
, "batch12", test_raw_oplock_batch12
);
4048 torture_suite_add_2smb_test(suite
, "batch13", test_raw_oplock_batch13
);
4049 torture_suite_add_2smb_test(suite
, "batch14", test_raw_oplock_batch14
);
4050 torture_suite_add_2smb_test(suite
, "batch15", test_raw_oplock_batch15
);
4051 torture_suite_add_2smb_test(suite
, "batch16", test_raw_oplock_batch16
);
4052 torture_suite_add_2smb_test(suite
, "batch17", test_raw_oplock_batch17
);
4053 torture_suite_add_2smb_test(suite
, "batch18", test_raw_oplock_batch18
);
4054 torture_suite_add_2smb_test(suite
, "batch19", test_raw_oplock_batch19
);
4055 torture_suite_add_2smb_test(suite
, "batch20", test_raw_oplock_batch20
);
4056 torture_suite_add_2smb_test(suite
, "batch21", test_raw_oplock_batch21
);
4057 torture_suite_add_2smb_test(suite
, "batch22", test_raw_oplock_batch22
);
4058 torture_suite_add_2smb_test(suite
, "batch23", test_raw_oplock_batch23
);
4059 torture_suite_add_2smb_test(suite
, "batch24", test_raw_oplock_batch24
);
4060 torture_suite_add_2smb_test(suite
, "batch25", test_raw_oplock_batch25
);
4061 torture_suite_add_2smb_test(suite
, "batch26", test_raw_oplock_batch26
);
4062 torture_suite_add_2smb_test(suite
, "stream1", test_raw_oplock_stream1
);
4063 torture_suite_add_1smb_test(suite
, "doc1", test_raw_oplock_doc
);
4064 torture_suite_add_2smb_test(suite
, "brl1", test_raw_oplock_brl1
);
4065 torture_suite_add_1smb_test(suite
, "brl2", test_raw_oplock_brl2
);
4066 torture_suite_add_1smb_test(suite
, "brl3", test_raw_oplock_brl3
);
4067 torture_suite_add_2smb_test(suite
, "brl4", test_raw_oplock_brl4
);
4073 stress testing of oplocks
4075 bool torture_bench_oplock(struct torture_context
*torture
)
4077 struct smbcli_state
**cli
;
4079 TALLOC_CTX
*mem_ctx
= talloc_new(torture
);
4080 int torture_nprocs
= torture_setting_int(torture
, "nprocs", 4);
4082 int timelimit
= torture_setting_int(torture
, "timelimit", 10);
4086 cli
= talloc_array(mem_ctx
, struct smbcli_state
*, torture_nprocs
);
4088 torture_comment(torture
, "Opening %d connections\n", torture_nprocs
);
4089 for (i
=0;i
<torture_nprocs
;i
++) {
4090 if (!torture_open_connection_ev(&cli
[i
], i
, torture
, torture
->ev
)) {
4093 talloc_steal(mem_ctx
, cli
[i
]);
4094 smbcli_oplock_handler(cli
[i
]->transport
, oplock_handler_close
,
4098 if (!torture_setup_dir(cli
[0], BASEDIR
)) {
4103 io
.ntcreatex
.level
= RAW_OPEN_NTCREATEX
;
4104 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
4105 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
4106 io
.ntcreatex
.in
.alloc_size
= 0;
4107 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
4108 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
4109 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
4110 io
.ntcreatex
.in
.create_options
= 0;
4111 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
4112 io
.ntcreatex
.in
.security_flags
= 0;
4113 io
.ntcreatex
.in
.fname
= BASEDIR
"\\test.dat";
4114 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
4115 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
4116 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
4118 tv
= timeval_current();
4121 we open the same file with SHARE_ACCESS_NONE from all the
4122 connections in a round robin fashion. Each open causes an
4123 oplock break on the previous connection, which is answered
4124 by the oplock_handler_close() to close the file.
4126 This measures how fast we can pass on oplocks, and stresses
4127 the oplock handling code
4129 torture_comment(torture
, "Running for %d seconds\n", timelimit
);
4130 while (timeval_elapsed(&tv
) < timelimit
) {
4131 for (i
=0;i
<torture_nprocs
;i
++) {
4134 status
= smb_raw_open(cli
[i
]->tree
, mem_ctx
, &io
);
4135 CHECK_STATUS(torture
, status
, NT_STATUS_OK
);
4139 if (torture_setting_bool(torture
, "progress", true)) {
4140 torture_comment(torture
, "%.2f ops/second\r", count
/timeval_elapsed(&tv
));
4144 torture_comment(torture
, "%.2f ops/second\n", count
/timeval_elapsed(&tv
));
4146 smb_raw_exit(cli
[torture_nprocs
-1]->session
);
4149 smb_raw_exit(cli
[0]->session
);
4150 smbcli_deltree(cli
[0]->tree
, BASEDIR
);
4151 talloc_free(mem_ctx
);
4156 static struct hold_oplock_info
{
4158 bool close_on_break
;
4159 uint32_t share_access
;
4162 { BASEDIR
"\\notshared_close", true,
4163 NTCREATEX_SHARE_ACCESS_NONE
, },
4164 { BASEDIR
"\\notshared_noclose", false,
4165 NTCREATEX_SHARE_ACCESS_NONE
, },
4166 { BASEDIR
"\\shared_close", true,
4167 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
|NTCREATEX_SHARE_ACCESS_DELETE
, },
4168 { BASEDIR
"\\shared_noclose", false,
4169 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
|NTCREATEX_SHARE_ACCESS_DELETE
, },
4172 static bool oplock_handler_hold(struct smbcli_transport
*transport
,
4173 uint16_t tid
, uint16_t fnum
, uint8_t level
,
4176 struct smbcli_tree
*tree
= (struct smbcli_tree
*)private_data
;
4177 struct hold_oplock_info
*info
;
4180 for (i
=0;i
<ARRAY_SIZE(hold_info
);i
++) {
4181 if (hold_info
[i
].fnum
== fnum
) break;
4184 if (i
== ARRAY_SIZE(hold_info
)) {
4185 printf("oplock break for unknown fnum %u\n", fnum
);
4189 info
= &hold_info
[i
];
4191 if (info
->close_on_break
) {
4192 printf("oplock break on %s - closing\n",
4194 oplock_handler_close(transport
, tid
, fnum
, level
, private_data
);
4198 printf("oplock break on %s - acking break\n", info
->fname
);
4200 return smbcli_oplock_ack(tree
, fnum
, OPLOCK_BREAK_TO_NONE
);
4205 used for manual testing of oplocks - especially interaction with
4206 other filesystems (such as NFS and local access)
4208 bool torture_hold_oplock(struct torture_context
*torture
,
4209 struct smbcli_state
*cli
)
4211 struct tevent_context
*ev
= torture
->ev
;
4214 printf("Setting up open files with oplocks in %s\n", BASEDIR
);
4216 torture_assert(torture
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
4218 smbcli_oplock_handler(cli
->transport
, oplock_handler_hold
, cli
->tree
);
4220 /* setup the files */
4221 for (i
=0;i
<ARRAY_SIZE(hold_info
);i
++) {
4226 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
4227 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
4228 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
4229 io
.ntcreatex
.in
.alloc_size
= 0;
4230 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
4231 io
.ntcreatex
.in
.share_access
= hold_info
[i
].share_access
;
4232 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
4233 io
.ntcreatex
.in
.create_options
= 0;
4234 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
4235 io
.ntcreatex
.in
.security_flags
= 0;
4236 io
.ntcreatex
.in
.fname
= hold_info
[i
].fname
;
4237 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
4238 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
4239 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
4240 printf("opening %s\n", hold_info
[i
].fname
);
4242 status
= smb_raw_open(cli
->tree
, cli
, &io
);
4243 if (!NT_STATUS_IS_OK(status
)) {
4244 printf("Failed to open %s - %s\n",
4245 hold_info
[i
].fname
, nt_errstr(status
));
4249 if (io
.ntcreatex
.out
.oplock_level
!= BATCH_OPLOCK_RETURN
) {
4250 printf("Oplock not granted for %s - expected %d but got %d\n",
4251 hold_info
[i
].fname
, BATCH_OPLOCK_RETURN
,
4252 io
.ntcreatex
.out
.oplock_level
);
4255 hold_info
[i
].fnum
= io
.ntcreatex
.out
.file
.fnum
;
4257 /* make the file non-zero size */
4258 if (smbcli_write(cli
->tree
, hold_info
[i
].fnum
, 0, &c
, 0, 1) != 1) {
4259 printf("Failed to write to file\n");
4264 printf("Waiting for oplock events\n");
4265 tevent_loop_wait(ev
);