2 Unix SMB/CIFS implementation.
3 basic raw test suite for oplocks
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "libcli/raw/libcliraw.h"
22 #include "libcli/raw/raw_proto.h"
23 #include "libcli/libcli.h"
24 #include "torture/util.h"
25 #include "lib/events/events.h"
26 #include "param/param.h"
27 #include "lib/cmdline/popt_common.h"
28 #include "libcli/resolve/resolve.h"
29 #include "torture/raw/proto.h"
31 #define CHECK_VAL(v, correct) do { \
32 if ((v) != (correct)) { \
33 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
34 __location__, #v, (int)v, (int)correct); \
38 #define CHECK_RANGE(v, min, max) do { \
39 if ((v) < (min) || (v) > (max)) { \
40 torture_warning(tctx, "(%s): wrong value for %s got " \
41 "%d - should be between %d and %d\n", \
42 __location__, #v, (int)v, (int)min, (int)max); \
45 #define CHECK_STRMATCH(v, correct) do { \
46 if (!v || strstr((v),(correct)) == NULL) { \
47 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got '%s' - should be '%s'\n", \
48 __location__, #v, v?v:"NULL", correct); \
53 #define CHECK_STATUS(tctx, status, correct) do { \
54 if (!NT_STATUS_EQUAL(status, correct)) { \
55 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
56 nt_errstr(status), nt_errstr(correct)); \
69 #define BASEDIR "\\test_oplock"
72 a handler function for oplock break requests. Ack it as a break to level II if possible
74 static bool oplock_handler_ack_to_given(struct smbcli_transport *transport,
75 uint16_t tid, uint16_t fnum,
76 uint8_t level, void *private_data)
78 struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
81 break_info.fnum = fnum;
82 break_info.level = level;
86 case OPLOCK_BREAK_TO_LEVEL_II:
89 case OPLOCK_BREAK_TO_NONE:
94 break_info.failures++;
96 printf("Acking to %s [0x%02X] in oplock handler\n",
99 return smbcli_oplock_ack(tree, fnum, level);
103 a handler function for oplock break requests. Ack it as a break to none
105 static bool oplock_handler_ack_to_none(struct smbcli_transport *transport,
106 uint16_t tid, uint16_t fnum,
107 uint8_t level, void *private_data)
109 struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
110 break_info.fnum = fnum;
111 break_info.level = level;
114 printf("Acking to none in oplock handler\n");
116 return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
120 a handler function for oplock break requests. Let it timeout
122 static bool oplock_handler_timeout(struct smbcli_transport *transport,
123 uint16_t tid, uint16_t fnum,
124 uint8_t level, void *private_data)
126 break_info.fnum = fnum;
127 break_info.level = level;
130 printf("Let oplock break timeout\n");
134 static void oplock_handler_close_recv(struct smbcli_request *req)
137 status = smbcli_request_simple_recv(req);
138 if (!NT_STATUS_IS_OK(status)) {
139 printf("close failed in oplock_handler_close\n");
140 break_info.failures++;
145 a handler function for oplock break requests - close the file
147 static bool oplock_handler_close(struct smbcli_transport *transport, uint16_t tid,
148 uint16_t fnum, uint8_t level, void *private_data)
151 struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
152 struct smbcli_request *req;
154 break_info.fnum = fnum;
155 break_info.level = level;
158 io.close.level = RAW_CLOSE_CLOSE;
159 io.close.in.file.fnum = fnum;
160 io.close.in.write_time = 0;
161 req = smb_raw_close_send(tree, &io);
163 printf("failed to send close in oplock_handler_close\n");
167 req->async.fn = oplock_handler_close_recv;
168 req->async.private_data = NULL;
173 static bool open_connection_no_level2_oplocks(struct torture_context *tctx,
174 struct smbcli_state **c)
177 struct smbcli_options options;
178 struct smbcli_session_options session_options;
180 lpcfg_smbcli_options(tctx->lp_ctx, &options);
181 lpcfg_smbcli_session_options(tctx->lp_ctx, &session_options);
183 options.use_level2_oplocks = false;
185 status = smbcli_full_connection(tctx, c,
186 torture_setting_string(tctx, "host", NULL),
187 lpcfg_smb_ports(tctx->lp_ctx),
188 torture_setting_string(tctx, "share", NULL),
189 NULL, lpcfg_socket_options(tctx->lp_ctx), cmdline_credentials,
190 lpcfg_resolve_context(tctx->lp_ctx),
191 tctx->ev, &options, &session_options,
192 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
193 if (!NT_STATUS_IS_OK(status)) {
194 torture_comment(tctx, "Failed to open connection - %s\n",
203 Timer handler function notifies the registering function that time is up
205 static void timeout_cb(struct tevent_context *ev,
206 struct tevent_timer *te,
207 struct timeval current_time,
210 bool *timesup = (bool *)private_data;
216 Wait a short period of time to receive a single oplock break request
218 static void torture_wait_for_oplock_break(struct torture_context *tctx)
220 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
221 struct tevent_timer *te = NULL;
223 bool timesup = false;
224 int old_count = break_info.count;
226 /* Wait .1 seconds for an oplock break */
227 ne = tevent_timeval_current_ofs(0, 100000);
229 if ((te = tevent_add_timer(tctx->ev, tmp_ctx, ne, timeout_cb, ×up))
232 torture_comment(tctx, "Failed to wait for an oplock break. "
233 "test results may not be accurate.");
237 while (!timesup && break_info.count < old_count + 1) {
238 if (tevent_loop_once(tctx->ev) != 0) {
239 torture_comment(tctx, "Failed to wait for an oplock "
240 "break. test results may not be "
247 /* We don't know if the timed event fired and was freed, we received
248 * our oplock break, or some other event triggered the loop. Thus,
249 * we create a tmp_ctx to be able to safely free/remove the timed
250 * event in all 3 cases. */
251 talloc_free(tmp_ctx);
256 static uint8_t get_break_level1_to_none_count(struct torture_context *tctx)
258 return torture_setting_bool(tctx, "2_step_break_to_none", false) ?
262 static uint8_t get_setinfo_break_count(struct torture_context *tctx)
264 if (TARGET_IS_W2K12(tctx)) {
270 static bool test_raw_oplock_exclusive1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
272 const char *fname = BASEDIR "\\test_exclusive1.dat";
276 union smb_unlink unl;
279 if (!torture_setup_dir(cli1, BASEDIR)) {
284 smbcli_unlink(cli1->tree, fname);
286 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
291 io.generic.level = RAW_OPEN_NTCREATEX;
292 io.ntcreatex.in.root_fid.fnum = 0;
293 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
294 io.ntcreatex.in.alloc_size = 0;
295 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
296 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
297 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
298 io.ntcreatex.in.create_options = 0;
299 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
300 io.ntcreatex.in.security_flags = 0;
301 io.ntcreatex.in.fname = fname;
303 torture_comment(tctx, "EXCLUSIVE1: open a file with an exclusive oplock (share mode: none)\n");
304 ZERO_STRUCT(break_info);
305 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
307 status = smb_raw_open(cli1->tree, tctx, &io);
308 CHECK_STATUS(tctx, status, NT_STATUS_OK);
309 fnum = io.ntcreatex.out.file.fnum;
310 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
312 torture_comment(tctx, "a 2nd open should not cause a break\n");
313 status = smb_raw_open(cli2->tree, tctx, &io);
314 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
315 torture_wait_for_oplock_break(tctx);
316 CHECK_VAL(break_info.count, 0);
317 CHECK_VAL(break_info.failures, 0);
319 torture_comment(tctx, "unlink it - should also be no break\n");
320 unl.unlink.in.pattern = fname;
321 unl.unlink.in.attrib = 0;
322 status = smb_raw_unlink(cli2->tree, &unl);
323 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
324 torture_wait_for_oplock_break(tctx);
325 CHECK_VAL(break_info.count, 0);
326 CHECK_VAL(break_info.failures, 0);
328 smbcli_close(cli1->tree, fnum);
331 smb_raw_exit(cli1->session);
332 smb_raw_exit(cli2->session);
333 smbcli_deltree(cli1->tree, BASEDIR);
337 static bool test_raw_oplock_exclusive2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
339 const char *fname = BASEDIR "\\test_exclusive2.dat";
343 union smb_unlink unl;
344 uint16_t fnum=0, fnum2=0;
346 if (!torture_setup_dir(cli1, BASEDIR)) {
351 smbcli_unlink(cli1->tree, fname);
353 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
358 io.generic.level = RAW_OPEN_NTCREATEX;
359 io.ntcreatex.in.root_fid.fnum = 0;
360 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
361 io.ntcreatex.in.alloc_size = 0;
362 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
363 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
364 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
365 io.ntcreatex.in.create_options = 0;
366 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
367 io.ntcreatex.in.security_flags = 0;
368 io.ntcreatex.in.fname = fname;
370 torture_comment(tctx, "EXCLUSIVE2: open a file with an exclusive oplock (share mode: all)\n");
371 ZERO_STRUCT(break_info);
372 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
373 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
374 NTCREATEX_SHARE_ACCESS_WRITE|
375 NTCREATEX_SHARE_ACCESS_DELETE;
377 status = smb_raw_open(cli1->tree, tctx, &io);
378 CHECK_STATUS(tctx, status, NT_STATUS_OK);
379 fnum = io.ntcreatex.out.file.fnum;
380 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
382 torture_comment(tctx, "a 2nd open should cause a break to level 2\n");
383 status = smb_raw_open(cli2->tree, tctx, &io);
384 CHECK_STATUS(tctx, status, NT_STATUS_OK);
385 fnum2 = io.ntcreatex.out.file.fnum;
386 torture_wait_for_oplock_break(tctx);
387 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
388 CHECK_VAL(break_info.count, 1);
389 CHECK_VAL(break_info.fnum, fnum);
390 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
391 CHECK_VAL(break_info.failures, 0);
392 ZERO_STRUCT(break_info);
394 /* now we have 2 level II oplocks... */
395 torture_comment(tctx, "try to unlink it - should not cause a break, but a sharing violation\n");
396 unl.unlink.in.pattern = fname;
397 unl.unlink.in.attrib = 0;
398 status = smb_raw_unlink(cli2->tree, &unl);
399 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
400 torture_wait_for_oplock_break(tctx);
401 CHECK_VAL(break_info.count, 0);
402 CHECK_VAL(break_info.failures, 0);
404 torture_comment(tctx, "close 1st handle\n");
405 smbcli_close(cli1->tree, fnum);
407 torture_comment(tctx, "try to unlink it - should not cause a break, but a sharing violation\n");
408 unl.unlink.in.pattern = fname;
409 unl.unlink.in.attrib = 0;
410 status = smb_raw_unlink(cli2->tree, &unl);
411 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
412 torture_wait_for_oplock_break(tctx);
413 CHECK_VAL(break_info.count, 0);
414 CHECK_VAL(break_info.failures, 0);
416 torture_comment(tctx, "close 2nd handle\n");
417 smbcli_close(cli2->tree, fnum2);
419 torture_comment(tctx, "unlink it\n");
420 unl.unlink.in.pattern = fname;
421 unl.unlink.in.attrib = 0;
422 status = smb_raw_unlink(cli2->tree, &unl);
423 CHECK_STATUS(tctx, status, NT_STATUS_OK);
424 torture_wait_for_oplock_break(tctx);
425 CHECK_VAL(break_info.count, 0);
426 CHECK_VAL(break_info.failures, 0);
429 smb_raw_exit(cli1->session);
430 smb_raw_exit(cli2->session);
431 smbcli_deltree(cli1->tree, BASEDIR);
435 static bool test_raw_oplock_exclusive3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
437 const char *fname = BASEDIR "\\test_exclusive3.dat";
441 union smb_setfileinfo sfi;
444 if (!torture_setup_dir(cli1, BASEDIR)) {
449 smbcli_unlink(cli1->tree, fname);
451 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
456 io.generic.level = RAW_OPEN_NTCREATEX;
457 io.ntcreatex.in.root_fid.fnum = 0;
458 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
459 io.ntcreatex.in.alloc_size = 0;
460 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
461 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE;
462 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
463 io.ntcreatex.in.create_options = 0;
464 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
465 io.ntcreatex.in.security_flags = 0;
466 io.ntcreatex.in.fname = fname;
468 torture_comment(tctx, "EXCLUSIVE3: open a file with an exclusive oplock (share mode: none)\n");
470 ZERO_STRUCT(break_info);
471 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
473 status = smb_raw_open(cli1->tree, tctx, &io);
474 CHECK_STATUS(tctx, status, NT_STATUS_OK);
475 fnum = io.ntcreatex.out.file.fnum;
476 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
478 torture_comment(tctx, "setpathinfo EOF should trigger a break to none\n");
480 sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
481 sfi.generic.in.file.path = fname;
482 sfi.end_of_file_info.in.size = 100;
484 status = smb_raw_setpathinfo(cli2->tree, &sfi);
486 CHECK_STATUS(tctx, status, NT_STATUS_OK);
487 torture_wait_for_oplock_break(tctx);
488 CHECK_VAL(break_info.count, get_setinfo_break_count(tctx));
489 CHECK_VAL(break_info.failures, 0);
490 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
492 smbcli_close(cli1->tree, fnum);
495 smb_raw_exit(cli1->session);
496 smb_raw_exit(cli2->session);
497 smbcli_deltree(cli1->tree, BASEDIR);
501 static bool test_raw_oplock_exclusive4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
503 const char *fname = BASEDIR "\\test_exclusive4.dat";
507 uint16_t fnum=0, fnum2=0;
509 if (!torture_setup_dir(cli1, BASEDIR)) {
514 smbcli_unlink(cli1->tree, fname);
516 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
521 io.generic.level = RAW_OPEN_NTCREATEX;
522 io.ntcreatex.in.root_fid.fnum = 0;
523 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
524 io.ntcreatex.in.alloc_size = 0;
525 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
526 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
527 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
528 io.ntcreatex.in.create_options = 0;
529 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
530 io.ntcreatex.in.security_flags = 0;
531 io.ntcreatex.in.fname = fname;
533 torture_comment(tctx, "EXCLUSIVE4: open with exclusive oplock\n");
534 ZERO_STRUCT(break_info);
535 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
537 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
538 status = smb_raw_open(cli1->tree, tctx, &io);
539 CHECK_STATUS(tctx, status, NT_STATUS_OK);
540 fnum = io.ntcreatex.out.file.fnum;
541 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
543 ZERO_STRUCT(break_info);
544 torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
546 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
547 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
548 status = smb_raw_open(cli2->tree, tctx, &io);
549 CHECK_STATUS(tctx, status, NT_STATUS_OK);
550 fnum2 = io.ntcreatex.out.file.fnum;
551 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
552 torture_wait_for_oplock_break(tctx);
553 CHECK_VAL(break_info.count, 0);
554 CHECK_VAL(break_info.failures, 0);
556 smbcli_close(cli1->tree, fnum);
557 smbcli_close(cli2->tree, fnum2);
560 smb_raw_exit(cli1->session);
561 smb_raw_exit(cli2->session);
562 smbcli_deltree(cli1->tree, BASEDIR);
566 static bool test_raw_oplock_exclusive5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
568 const char *fname = BASEDIR "\\test_exclusive5.dat";
572 uint16_t fnum=0, fnum2=0;
574 if (!torture_setup_dir(cli1, BASEDIR)) {
579 smbcli_unlink(cli1->tree, fname);
581 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
582 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
587 io.generic.level = RAW_OPEN_NTCREATEX;
588 io.ntcreatex.in.root_fid.fnum = 0;
589 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
590 io.ntcreatex.in.alloc_size = 0;
591 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
592 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
593 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
594 io.ntcreatex.in.create_options = 0;
595 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
596 io.ntcreatex.in.security_flags = 0;
597 io.ntcreatex.in.fname = fname;
599 torture_comment(tctx, "EXCLUSIVE5: open with exclusive oplock\n");
600 ZERO_STRUCT(break_info);
601 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
604 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
605 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
606 NTCREATEX_SHARE_ACCESS_WRITE|
607 NTCREATEX_SHARE_ACCESS_DELETE;
608 status = smb_raw_open(cli1->tree, tctx, &io);
609 CHECK_STATUS(tctx, status, NT_STATUS_OK);
610 fnum = io.ntcreatex.out.file.fnum;
611 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
613 ZERO_STRUCT(break_info);
615 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
617 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
618 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
619 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
620 status = smb_raw_open(cli2->tree, tctx, &io);
621 CHECK_STATUS(tctx, status, NT_STATUS_OK);
622 fnum2 = io.ntcreatex.out.file.fnum;
623 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
624 torture_wait_for_oplock_break(tctx);
625 CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
626 CHECK_VAL(break_info.failures, 0);
628 smbcli_close(cli1->tree, fnum);
629 smbcli_close(cli2->tree, fnum2);
632 smb_raw_exit(cli1->session);
633 smb_raw_exit(cli2->session);
634 smbcli_deltree(cli1->tree, BASEDIR);
638 static bool test_raw_oplock_exclusive6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
640 const char *fname1 = BASEDIR "\\test_exclusive6_1.dat";
641 const char *fname2 = BASEDIR "\\test_exclusive6_2.dat";
648 if (!torture_setup_dir(cli1, BASEDIR)) {
653 smbcli_unlink(cli1->tree, fname1);
654 smbcli_unlink(cli1->tree, fname2);
656 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
661 io.generic.level = RAW_OPEN_NTCREATEX;
662 io.ntcreatex.in.root_fid.fnum = 0;
663 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
664 io.ntcreatex.in.alloc_size = 0;
665 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
666 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
667 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
668 io.ntcreatex.in.create_options = 0;
669 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
670 io.ntcreatex.in.security_flags = 0;
671 io.ntcreatex.in.fname = fname1;
673 torture_comment(tctx, "EXCLUSIVE6: open a file with an exclusive "
674 "oplock (share mode: none)\n");
675 ZERO_STRUCT(break_info);
676 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
678 status = smb_raw_open(cli1->tree, tctx, &io);
679 CHECK_STATUS(tctx, status, NT_STATUS_OK);
680 fnum = io.ntcreatex.out.file.fnum;
681 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
683 torture_comment(tctx, "rename should not generate a break but get a "
684 "sharing violation\n");
686 rn.generic.level = RAW_RENAME_RENAME;
687 rn.rename.in.pattern1 = fname1;
688 rn.rename.in.pattern2 = fname2;
689 rn.rename.in.attrib = 0;
691 torture_comment(tctx, "trying rename while first file open\n");
692 status = smb_raw_rename(cli2->tree, &rn);
694 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
695 torture_wait_for_oplock_break(tctx);
696 CHECK_VAL(break_info.count, 0);
697 CHECK_VAL(break_info.failures, 0);
699 smbcli_close(cli1->tree, fnum);
702 smb_raw_exit(cli1->session);
703 smb_raw_exit(cli2->session);
704 smbcli_deltree(cli1->tree, BASEDIR);
709 * Exclusive version of batch19
711 static bool test_raw_oplock_exclusive7(struct torture_context *tctx,
712 struct smbcli_state *cli1, struct smbcli_state *cli2)
714 const char *fname1 = BASEDIR "\\test_exclusiv6_1.dat";
715 const char *fname2 = BASEDIR "\\test_exclusiv6_2.dat";
716 const char *fname3 = BASEDIR "\\test_exclusiv6_3.dat";
720 union smb_fileinfo qfi;
721 union smb_setfileinfo sfi;
725 if (!torture_setup_dir(cli1, BASEDIR)) {
730 smbcli_unlink(cli1->tree, fname1);
731 smbcli_unlink(cli1->tree, fname2);
732 smbcli_unlink(cli1->tree, fname3);
734 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
740 io.generic.level = RAW_OPEN_NTCREATEX;
741 io.ntcreatex.in.root_fid.fnum = 0;
742 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
743 io.ntcreatex.in.alloc_size = 0;
744 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
745 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
746 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
747 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
748 io.ntcreatex.in.create_options = 0;
749 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
750 io.ntcreatex.in.security_flags = 0;
751 io.ntcreatex.in.fname = fname1;
753 torture_comment(tctx, "open a file with an exclusive oplock (share "
755 ZERO_STRUCT(break_info);
756 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
757 NTCREATEX_FLAGS_REQUEST_OPLOCK;
758 status = smb_raw_open(cli1->tree, tctx, &io);
759 CHECK_STATUS(tctx, status, NT_STATUS_OK);
760 fnum = io.ntcreatex.out.file.fnum;
761 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
763 torture_comment(tctx, "setpathinfo rename info should trigger a break "
766 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
767 sfi.generic.in.file.path = fname1;
768 sfi.rename_information.in.overwrite = 0;
769 sfi.rename_information.in.root_fid = 0;
770 sfi.rename_information.in.new_name = fname2+strlen(BASEDIR)+1;
772 status = smb_raw_setpathinfo(cli2->tree, &sfi);
773 CHECK_STATUS(tctx, status, NT_STATUS_OK);
775 torture_wait_for_oplock_break(tctx);
776 CHECK_VAL(break_info.failures, 0);
778 if (TARGET_IS_WINXP(tctx) || TARGET_IS_W2K12(tctx)) {
779 /* XP incorrectly breaks to level2. */
780 CHECK_VAL(break_info.count, 1);
781 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
783 /* Exclusive oplocks should not be broken on rename. */
784 CHECK_VAL(break_info.failures, 0);
785 CHECK_VAL(break_info.count, 0);
789 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
790 qfi.generic.in.file.fnum = fnum;
792 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
793 CHECK_STATUS(tctx, status, NT_STATUS_OK);
794 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
796 /* Try breaking to level2 and then see if rename breaks the level2.*/
797 ZERO_STRUCT(break_info);
798 io.ntcreatex.in.fname = fname2;
799 status = smb_raw_open(cli2->tree, tctx, &io);
800 CHECK_STATUS(tctx, status, NT_STATUS_OK);
801 fnum2 = io.ntcreatex.out.file.fnum;
802 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
804 torture_wait_for_oplock_break(tctx);
805 CHECK_VAL(break_info.failures, 0);
807 if (TARGET_IS_WINXP(tctx)) {
808 /* XP already broke to level2. */
809 CHECK_VAL(break_info.failures, 0);
810 CHECK_VAL(break_info.count, 0);
811 } else if (TARGET_IS_W2K12(tctx)) {
813 CHECK_VAL(break_info.count, 0);
814 CHECK_VAL(break_info.level, 0);
816 /* Break to level 2 expected. */
817 CHECK_VAL(break_info.count, 1);
818 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
821 ZERO_STRUCT(break_info);
822 sfi.generic.in.file.path = fname2;
823 sfi.rename_information.in.overwrite = 0;
824 sfi.rename_information.in.root_fid = 0;
825 sfi.rename_information.in.new_name = fname1+strlen(BASEDIR)+1;
827 status = smb_raw_setpathinfo(cli2->tree, &sfi);
828 CHECK_STATUS(tctx, status, NT_STATUS_OK);
830 /* Level2 oplocks are not broken on rename. */
831 torture_wait_for_oplock_break(tctx);
832 CHECK_VAL(break_info.failures, 0);
833 CHECK_VAL(break_info.count, 0);
835 /* Close and re-open file with oplock. */
836 smbcli_close(cli1->tree, fnum);
837 status = smb_raw_open(cli1->tree, tctx, &io);
838 CHECK_STATUS(tctx, status, NT_STATUS_OK);
839 fnum = io.ntcreatex.out.file.fnum;
840 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
842 torture_comment(tctx, "setfileinfo rename info on a client's own fid "
843 "should not trigger a break nor a violation\n");
844 ZERO_STRUCT(break_info);
846 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
847 sfi.generic.in.file.fnum = fnum;
848 sfi.rename_information.in.overwrite = 0;
849 sfi.rename_information.in.root_fid = 0;
850 sfi.rename_information.in.new_name = fname3+strlen(BASEDIR)+1;
852 status = smb_raw_setfileinfo(cli1->tree, &sfi);
853 CHECK_STATUS(tctx, status, NT_STATUS_OK);
855 torture_wait_for_oplock_break(tctx);
856 if (TARGET_IS_WINXP(tctx)) {
857 /* XP incorrectly breaks to level2. */
858 CHECK_VAL(break_info.count, 1);
859 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
861 CHECK_VAL(break_info.count, 0);
865 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
866 qfi.generic.in.file.fnum = fnum;
868 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
869 CHECK_STATUS(tctx, status, NT_STATUS_OK);
870 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
873 smbcli_close(cli1->tree, fnum);
874 smbcli_close(cli2->tree, fnum2);
876 smb_raw_exit(cli1->session);
877 smb_raw_exit(cli2->session);
878 smbcli_deltree(cli1->tree, BASEDIR);
882 static bool test_raw_oplock_exclusive8(struct torture_context *tctx,
883 struct smbcli_state *cli1,
884 struct smbcli_state *cli2)
886 const char *fname = BASEDIR "\\test_exclusive8.dat";
894 if (!torture_setup_dir(cli1, BASEDIR)) {
899 smbcli_unlink(cli1->tree, fname);
901 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
907 io.generic.level = RAW_OPEN_NTCREATEX;
908 io.ntcreatex.in.root_fid.fnum = 0;
909 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
910 io.ntcreatex.in.alloc_size = 0;
911 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
912 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
913 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
914 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
915 io.ntcreatex.in.create_options = 0;
916 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
917 io.ntcreatex.in.security_flags = 0;
918 io.ntcreatex.in.fname = fname;
920 torture_comment(tctx, "open a file with an exclusive oplock (share "
922 ZERO_STRUCT(break_info);
923 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
924 NTCREATEX_FLAGS_REQUEST_OPLOCK;
925 status = smb_raw_open(cli1->tree, tctx, &io);
926 CHECK_STATUS(tctx, status, NT_STATUS_OK);
927 fnum1 = io.ntcreatex.out.file.fnum;
928 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
930 torture_comment(tctx, "second open with delete should trigger a "
933 io.ntcreatex.in.access_mask = SEC_STD_DELETE;
934 io.ntcreatex.in.flags = 0;
935 status = smb_raw_open(cli2->tree, tctx, &io);
936 CHECK_STATUS(tctx, status, NT_STATUS_OK);
937 fnum2 = io.ntcreatex.out.file.fnum;
938 CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
939 CHECK_VAL(break_info.failures, 0);
940 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
942 /* Trigger a little panic in "old" samba code.. */
943 status = smb_raw_open(cli2->tree, tctx, &io);
944 CHECK_STATUS(tctx, status, NT_STATUS_OK);
945 fnum3 = io.ntcreatex.out.file.fnum;
947 smbcli_close(cli2->tree, fnum3);
948 smbcli_close(cli2->tree, fnum2);
949 smbcli_close(cli1->tree, fnum1);
952 smbcli_deltree(cli1->tree, BASEDIR);
953 smb_raw_exit(cli1->session);
954 smb_raw_exit(cli2->session);
958 static bool test_raw_oplock_batch1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
960 const char *fname = BASEDIR "\\test_batch1.dat";
964 union smb_unlink unl;
968 if (!torture_setup_dir(cli1, BASEDIR)) {
973 smbcli_unlink(cli1->tree, fname);
975 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
980 io.generic.level = RAW_OPEN_NTCREATEX;
981 io.ntcreatex.in.root_fid.fnum = 0;
982 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
983 io.ntcreatex.in.alloc_size = 0;
984 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
985 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
986 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
987 io.ntcreatex.in.create_options = 0;
988 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
989 io.ntcreatex.in.security_flags = 0;
990 io.ntcreatex.in.fname = fname;
993 with a batch oplock we get a break
995 torture_comment(tctx, "BATCH1: open with batch oplock\n");
996 ZERO_STRUCT(break_info);
997 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
998 NTCREATEX_FLAGS_REQUEST_OPLOCK |
999 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1000 status = smb_raw_open(cli1->tree, tctx, &io);
1001 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1002 fnum = io.ntcreatex.out.file.fnum;
1003 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1005 torture_comment(tctx, "unlink should generate a break\n");
1006 unl.unlink.in.pattern = fname;
1007 unl.unlink.in.attrib = 0;
1008 status = smb_raw_unlink(cli2->tree, &unl);
1009 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1011 torture_wait_for_oplock_break(tctx);
1012 CHECK_VAL(break_info.count, 1);
1013 CHECK_VAL(break_info.fnum, fnum);
1014 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1015 CHECK_VAL(break_info.failures, 0);
1017 torture_comment(tctx, "2nd unlink should not generate a break\n");
1018 ZERO_STRUCT(break_info);
1019 status = smb_raw_unlink(cli2->tree, &unl);
1020 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1022 torture_wait_for_oplock_break(tctx);
1023 CHECK_VAL(break_info.count, 0);
1025 torture_comment(tctx, "writing should generate a self break to none\n");
1026 smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
1028 torture_wait_for_oplock_break(tctx);
1029 torture_wait_for_oplock_break(tctx);
1030 CHECK_VAL(break_info.count, 1);
1031 CHECK_VAL(break_info.fnum, fnum);
1032 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
1033 CHECK_VAL(break_info.failures, 0);
1035 smbcli_close(cli1->tree, fnum);
1038 smb_raw_exit(cli1->session);
1039 smb_raw_exit(cli2->session);
1040 smbcli_deltree(cli1->tree, BASEDIR);
1044 static bool test_raw_oplock_batch2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1046 const char *fname = BASEDIR "\\test_batch2.dat";
1050 union smb_unlink unl;
1054 if (!torture_setup_dir(cli1, BASEDIR)) {
1059 smbcli_unlink(cli1->tree, fname);
1061 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1064 base ntcreatex parms
1066 io.generic.level = RAW_OPEN_NTCREATEX;
1067 io.ntcreatex.in.root_fid.fnum = 0;
1068 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1069 io.ntcreatex.in.alloc_size = 0;
1070 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1071 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1072 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1073 io.ntcreatex.in.create_options = 0;
1074 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1075 io.ntcreatex.in.security_flags = 0;
1076 io.ntcreatex.in.fname = fname;
1078 torture_comment(tctx, "BATCH2: open with batch oplock\n");
1079 ZERO_STRUCT(break_info);
1080 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1081 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1082 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1083 status = smb_raw_open(cli1->tree, tctx, &io);
1084 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1085 fnum = io.ntcreatex.out.file.fnum;
1086 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1088 torture_comment(tctx, "unlink should generate a break, which we ack as break to none\n");
1089 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_none, cli1->tree);
1090 unl.unlink.in.pattern = fname;
1091 unl.unlink.in.attrib = 0;
1092 status = smb_raw_unlink(cli2->tree, &unl);
1093 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1095 torture_wait_for_oplock_break(tctx);
1096 CHECK_VAL(break_info.count, 1);
1097 CHECK_VAL(break_info.fnum, fnum);
1098 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1099 CHECK_VAL(break_info.failures, 0);
1101 torture_comment(tctx, "2nd unlink should not generate a break\n");
1102 ZERO_STRUCT(break_info);
1103 status = smb_raw_unlink(cli2->tree, &unl);
1104 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1106 torture_wait_for_oplock_break(tctx);
1107 CHECK_VAL(break_info.count, 0);
1109 torture_comment(tctx, "writing should not generate a break\n");
1110 smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
1112 torture_wait_for_oplock_break(tctx);
1113 CHECK_VAL(break_info.count, 0);
1115 smbcli_close(cli1->tree, fnum);
1118 smb_raw_exit(cli1->session);
1119 smb_raw_exit(cli2->session);
1120 smbcli_deltree(cli1->tree, BASEDIR);
1124 static bool test_raw_oplock_batch3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1126 const char *fname = BASEDIR "\\test_batch3.dat";
1130 union smb_unlink unl;
1133 if (!torture_setup_dir(cli1, BASEDIR)) {
1138 smbcli_unlink(cli1->tree, fname);
1140 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1143 base ntcreatex parms
1145 io.generic.level = RAW_OPEN_NTCREATEX;
1146 io.ntcreatex.in.root_fid.fnum = 0;
1147 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1148 io.ntcreatex.in.alloc_size = 0;
1149 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1150 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1151 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1152 io.ntcreatex.in.create_options = 0;
1153 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1154 io.ntcreatex.in.security_flags = 0;
1155 io.ntcreatex.in.fname = fname;
1157 torture_comment(tctx, "BATCH3: if we close on break then the unlink can succeed\n");
1158 ZERO_STRUCT(break_info);
1159 smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
1160 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1161 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1162 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1163 status = smb_raw_open(cli1->tree, tctx, &io);
1164 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1165 fnum = io.ntcreatex.out.file.fnum;
1166 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1168 unl.unlink.in.pattern = fname;
1169 unl.unlink.in.attrib = 0;
1170 ZERO_STRUCT(break_info);
1171 status = smb_raw_unlink(cli2->tree, &unl);
1172 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1174 torture_wait_for_oplock_break(tctx);
1175 CHECK_VAL(break_info.count, 1);
1176 CHECK_VAL(break_info.fnum, fnum);
1177 CHECK_VAL(break_info.level, 1);
1178 CHECK_VAL(break_info.failures, 0);
1180 smbcli_close(cli1->tree, fnum);
1183 smb_raw_exit(cli1->session);
1184 smb_raw_exit(cli2->session);
1185 smbcli_deltree(cli1->tree, BASEDIR);
1189 static bool test_raw_oplock_batch4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1191 const char *fname = BASEDIR "\\test_batch4.dat";
1198 if (!torture_setup_dir(cli1, BASEDIR)) {
1203 smbcli_unlink(cli1->tree, fname);
1205 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1208 base ntcreatex parms
1210 io.generic.level = RAW_OPEN_NTCREATEX;
1211 io.ntcreatex.in.root_fid.fnum = 0;
1212 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1213 io.ntcreatex.in.alloc_size = 0;
1214 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1215 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1216 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1217 io.ntcreatex.in.create_options = 0;
1218 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1219 io.ntcreatex.in.security_flags = 0;
1220 io.ntcreatex.in.fname = fname;
1222 torture_comment(tctx, "BATCH4: a self read should not cause a break\n");
1223 ZERO_STRUCT(break_info);
1224 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1226 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1227 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1228 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1229 status = smb_raw_open(cli1->tree, tctx, &io);
1230 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1231 fnum = io.ntcreatex.out.file.fnum;
1232 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1234 rd.readx.level = RAW_READ_READX;
1235 rd.readx.in.file.fnum = fnum;
1236 rd.readx.in.mincnt = 1;
1237 rd.readx.in.maxcnt = 1;
1238 rd.readx.in.offset = 0;
1239 rd.readx.in.remaining = 0;
1240 rd.readx.in.read_for_execute = false;
1241 status = smb_raw_read(cli1->tree, &rd);
1242 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1243 torture_wait_for_oplock_break(tctx);
1244 CHECK_VAL(break_info.count, 0);
1245 CHECK_VAL(break_info.failures, 0);
1247 smbcli_close(cli1->tree, fnum);
1250 smb_raw_exit(cli1->session);
1251 smb_raw_exit(cli2->session);
1252 smbcli_deltree(cli1->tree, BASEDIR);
1256 static bool test_raw_oplock_batch5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1258 const char *fname = BASEDIR "\\test_batch5.dat";
1264 if (!torture_setup_dir(cli1, BASEDIR)) {
1269 smbcli_unlink(cli1->tree, fname);
1271 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1274 base ntcreatex parms
1276 io.generic.level = RAW_OPEN_NTCREATEX;
1277 io.ntcreatex.in.root_fid.fnum = 0;
1278 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1279 io.ntcreatex.in.alloc_size = 0;
1280 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1281 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1282 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1283 io.ntcreatex.in.create_options = 0;
1284 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1285 io.ntcreatex.in.security_flags = 0;
1286 io.ntcreatex.in.fname = fname;
1288 torture_comment(tctx, "BATCH5: a 2nd open should give a break\n");
1289 ZERO_STRUCT(break_info);
1290 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1292 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1293 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1294 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1295 status = smb_raw_open(cli1->tree, tctx, &io);
1296 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1297 fnum = io.ntcreatex.out.file.fnum;
1298 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1300 ZERO_STRUCT(break_info);
1302 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1303 status = smb_raw_open(cli2->tree, tctx, &io);
1304 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1306 torture_wait_for_oplock_break(tctx);
1307 CHECK_VAL(break_info.count, 1);
1308 CHECK_VAL(break_info.fnum, fnum);
1309 CHECK_VAL(break_info.level, 1);
1310 CHECK_VAL(break_info.failures, 0);
1312 smbcli_close(cli1->tree, fnum);
1315 smb_raw_exit(cli1->session);
1316 smb_raw_exit(cli2->session);
1317 smbcli_deltree(cli1->tree, BASEDIR);
1321 static bool test_raw_oplock_batch6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1323 const char *fname = BASEDIR "\\test_batch6.dat";
1327 uint16_t fnum=0, fnum2=0;
1330 if (!torture_setup_dir(cli1, BASEDIR)) {
1335 smbcli_unlink(cli1->tree, fname);
1337 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1338 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1341 base ntcreatex parms
1343 io.generic.level = RAW_OPEN_NTCREATEX;
1344 io.ntcreatex.in.root_fid.fnum = 0;
1345 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1346 io.ntcreatex.in.alloc_size = 0;
1347 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1348 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1349 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1350 io.ntcreatex.in.create_options = 0;
1351 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1352 io.ntcreatex.in.security_flags = 0;
1353 io.ntcreatex.in.fname = fname;
1355 torture_comment(tctx, "BATCH6: a 2nd open should give a break to level II if the first open allowed shared read\n");
1356 ZERO_STRUCT(break_info);
1358 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
1359 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
1360 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1361 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1362 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1363 status = smb_raw_open(cli1->tree, tctx, &io);
1364 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1365 fnum = io.ntcreatex.out.file.fnum;
1366 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1368 ZERO_STRUCT(break_info);
1370 status = smb_raw_open(cli2->tree, tctx, &io);
1371 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1372 fnum2 = io.ntcreatex.out.file.fnum;
1373 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1375 //torture_wait_for_oplock_break(tctx);
1376 CHECK_VAL(break_info.count, 1);
1377 CHECK_VAL(break_info.fnum, fnum);
1378 CHECK_VAL(break_info.level, 1);
1379 CHECK_VAL(break_info.failures, 0);
1380 ZERO_STRUCT(break_info);
1382 torture_comment(tctx, "write should trigger a break to none on both\n");
1383 smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
1385 /* We expect two breaks */
1386 torture_wait_for_oplock_break(tctx);
1387 torture_wait_for_oplock_break(tctx);
1389 CHECK_VAL(break_info.count, 2);
1390 CHECK_VAL(break_info.level, 0);
1391 CHECK_VAL(break_info.failures, 0);
1393 smbcli_close(cli1->tree, fnum);
1394 smbcli_close(cli2->tree, fnum2);
1397 smb_raw_exit(cli1->session);
1398 smb_raw_exit(cli2->session);
1399 smbcli_deltree(cli1->tree, BASEDIR);
1403 static bool test_raw_oplock_batch7(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1405 const char *fname = BASEDIR "\\test_batch7.dat";
1409 uint16_t fnum=0, fnum2=0;
1411 if (!torture_setup_dir(cli1, BASEDIR)) {
1416 smbcli_unlink(cli1->tree, fname);
1418 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1421 base ntcreatex parms
1423 io.generic.level = RAW_OPEN_NTCREATEX;
1424 io.ntcreatex.in.root_fid.fnum = 0;
1425 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1426 io.ntcreatex.in.alloc_size = 0;
1427 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1428 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1429 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1430 io.ntcreatex.in.create_options = 0;
1431 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1432 io.ntcreatex.in.security_flags = 0;
1433 io.ntcreatex.in.fname = fname;
1435 torture_comment(tctx, "BATCH7: a 2nd open should get an oplock when we close instead of ack\n");
1436 ZERO_STRUCT(break_info);
1437 smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
1439 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1440 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1441 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1442 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1443 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1444 status = smb_raw_open(cli1->tree, tctx, &io);
1445 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1446 fnum2 = io.ntcreatex.out.file.fnum;
1447 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1449 ZERO_STRUCT(break_info);
1451 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1452 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1453 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1454 status = smb_raw_open(cli2->tree, tctx, &io);
1455 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1456 fnum = io.ntcreatex.out.file.fnum;
1457 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1459 torture_wait_for_oplock_break(tctx);
1460 CHECK_VAL(break_info.count, 1);
1461 CHECK_VAL(break_info.fnum, fnum2);
1462 CHECK_VAL(break_info.level, 1);
1463 CHECK_VAL(break_info.failures, 0);
1465 smbcli_close(cli2->tree, fnum);
1468 smb_raw_exit(cli1->session);
1469 smb_raw_exit(cli2->session);
1470 smbcli_deltree(cli1->tree, BASEDIR);
1474 static bool test_raw_oplock_batch8(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1476 const char *fname = BASEDIR "\\test_batch8.dat";
1480 uint16_t fnum=0, fnum2=0;
1482 if (!torture_setup_dir(cli1, BASEDIR)) {
1487 smbcli_unlink(cli1->tree, fname);
1489 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1492 base ntcreatex parms
1494 io.generic.level = RAW_OPEN_NTCREATEX;
1495 io.ntcreatex.in.root_fid.fnum = 0;
1496 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1497 io.ntcreatex.in.alloc_size = 0;
1498 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1499 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1500 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1501 io.ntcreatex.in.create_options = 0;
1502 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1503 io.ntcreatex.in.security_flags = 0;
1504 io.ntcreatex.in.fname = fname;
1506 torture_comment(tctx, "BATCH8: open with batch oplock\n");
1507 ZERO_STRUCT(break_info);
1508 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1510 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1511 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1512 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1513 status = smb_raw_open(cli1->tree, tctx, &io);
1514 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1515 fnum = io.ntcreatex.out.file.fnum;
1516 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1518 ZERO_STRUCT(break_info);
1519 torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
1521 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1522 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1523 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1524 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1525 status = smb_raw_open(cli2->tree, tctx, &io);
1526 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1527 fnum2 = io.ntcreatex.out.file.fnum;
1528 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
1529 torture_wait_for_oplock_break(tctx);
1530 CHECK_VAL(break_info.count, 0);
1531 CHECK_VAL(break_info.failures, 0);
1533 smbcli_close(cli1->tree, fnum);
1534 smbcli_close(cli2->tree, fnum2);
1537 smb_raw_exit(cli1->session);
1538 smb_raw_exit(cli2->session);
1539 smbcli_deltree(cli1->tree, BASEDIR);
1543 static bool test_raw_oplock_batch9(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1545 const char *fname = BASEDIR "\\test_batch9.dat";
1549 uint16_t fnum=0, fnum2=0;
1552 if (!torture_setup_dir(cli1, BASEDIR)) {
1557 smbcli_unlink(cli1->tree, fname);
1559 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1562 base ntcreatex parms
1564 io.generic.level = RAW_OPEN_NTCREATEX;
1565 io.ntcreatex.in.root_fid.fnum = 0;
1566 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1567 io.ntcreatex.in.alloc_size = 0;
1568 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1569 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1570 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1571 io.ntcreatex.in.create_options = 0;
1572 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1573 io.ntcreatex.in.security_flags = 0;
1574 io.ntcreatex.in.fname = fname;
1576 torture_comment(tctx, "BATCH9: open with attributes only can create file\n");
1578 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1579 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1580 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1581 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1582 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1583 status = smb_raw_open(cli1->tree, tctx, &io);
1584 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1585 fnum = io.ntcreatex.out.file.fnum;
1586 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1588 torture_comment(tctx, "Subsequent normal open should break oplock on attribute only open to level II\n");
1590 ZERO_STRUCT(break_info);
1591 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1593 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1594 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1595 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1596 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1597 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1598 status = smb_raw_open(cli2->tree, tctx, &io);
1599 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1600 fnum2 = io.ntcreatex.out.file.fnum;
1601 torture_wait_for_oplock_break(tctx);
1602 CHECK_VAL(break_info.count, 1);
1603 CHECK_VAL(break_info.fnum, fnum);
1604 CHECK_VAL(break_info.failures, 0);
1605 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1606 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1607 smbcli_close(cli2->tree, fnum2);
1609 torture_comment(tctx, "third oplocked open should grant level2 without break\n");
1610 ZERO_STRUCT(break_info);
1611 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1612 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1613 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1614 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1615 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1616 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1617 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1618 status = smb_raw_open(cli2->tree, tctx, &io);
1619 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1620 fnum2 = io.ntcreatex.out.file.fnum;
1621 torture_wait_for_oplock_break(tctx);
1622 CHECK_VAL(break_info.count, 0);
1623 CHECK_VAL(break_info.failures, 0);
1624 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1626 ZERO_STRUCT(break_info);
1628 torture_comment(tctx, "write should trigger a break to none on both\n");
1629 smbcli_write(cli2->tree, fnum2, 0, &c, 0, 1);
1631 /* We expect two breaks */
1632 torture_wait_for_oplock_break(tctx);
1633 torture_wait_for_oplock_break(tctx);
1635 CHECK_VAL(break_info.count, 2);
1636 CHECK_VAL(break_info.level, 0);
1637 CHECK_VAL(break_info.failures, 0);
1639 smbcli_close(cli1->tree, fnum);
1640 smbcli_close(cli2->tree, fnum2);
1643 smb_raw_exit(cli1->session);
1644 smb_raw_exit(cli2->session);
1645 smbcli_deltree(cli1->tree, BASEDIR);
1649 static bool test_raw_oplock_batch10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1651 const char *fname = BASEDIR "\\test_batch10.dat";
1655 uint16_t fnum=0, fnum2=0;
1657 if (!torture_setup_dir(cli1, BASEDIR)) {
1662 smbcli_unlink(cli1->tree, fname);
1664 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1667 base ntcreatex parms
1669 io.generic.level = RAW_OPEN_NTCREATEX;
1670 io.ntcreatex.in.root_fid.fnum = 0;
1671 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1672 io.ntcreatex.in.alloc_size = 0;
1673 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1674 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1675 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1676 io.ntcreatex.in.create_options = 0;
1677 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1678 io.ntcreatex.in.security_flags = 0;
1679 io.ntcreatex.in.fname = fname;
1681 torture_comment(tctx, "BATCH10: Open with oplock after a non-oplock open should grant level2\n");
1682 ZERO_STRUCT(break_info);
1683 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1684 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1685 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1686 NTCREATEX_SHARE_ACCESS_WRITE|
1687 NTCREATEX_SHARE_ACCESS_DELETE;
1688 status = smb_raw_open(cli1->tree, tctx, &io);
1689 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1690 fnum = io.ntcreatex.out.file.fnum;
1691 torture_wait_for_oplock_break(tctx);
1692 CHECK_VAL(break_info.count, 0);
1693 CHECK_VAL(break_info.failures, 0);
1694 CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
1696 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1698 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1699 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1700 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1701 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1702 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1703 NTCREATEX_SHARE_ACCESS_WRITE|
1704 NTCREATEX_SHARE_ACCESS_DELETE;
1705 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1706 status = smb_raw_open(cli2->tree, tctx, &io);
1707 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1708 fnum2 = io.ntcreatex.out.file.fnum;
1709 torture_wait_for_oplock_break(tctx);
1710 CHECK_VAL(break_info.count, 0);
1711 CHECK_VAL(break_info.failures, 0);
1712 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1714 torture_comment(tctx, "write should trigger a break to none\n");
1717 wr.write.level = RAW_WRITE_WRITE;
1718 wr.write.in.file.fnum = fnum;
1719 wr.write.in.count = 1;
1720 wr.write.in.offset = 0;
1721 wr.write.in.remaining = 0;
1722 wr.write.in.data = (const uint8_t *)"x";
1723 status = smb_raw_write(cli1->tree, &wr);
1724 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1727 torture_wait_for_oplock_break(tctx);
1729 CHECK_VAL(break_info.count, 1);
1730 CHECK_VAL(break_info.fnum, fnum2);
1731 CHECK_VAL(break_info.level, 0);
1732 CHECK_VAL(break_info.failures, 0);
1734 smbcli_close(cli1->tree, fnum);
1735 smbcli_close(cli2->tree, fnum2);
1738 smb_raw_exit(cli1->session);
1739 smb_raw_exit(cli2->session);
1740 smbcli_deltree(cli1->tree, BASEDIR);
1744 static bool test_raw_oplock_batch11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1746 const char *fname = BASEDIR "\\test_batch11.dat";
1750 union smb_setfileinfo sfi;
1753 if (!torture_setup_dir(cli1, BASEDIR)) {
1758 smbcli_unlink(cli1->tree, fname);
1760 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1763 base ntcreatex parms
1765 io.generic.level = RAW_OPEN_NTCREATEX;
1766 io.ntcreatex.in.root_fid.fnum = 0;
1767 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1768 io.ntcreatex.in.alloc_size = 0;
1769 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1770 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE;
1771 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1772 io.ntcreatex.in.create_options = 0;
1773 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1774 io.ntcreatex.in.security_flags = 0;
1775 io.ntcreatex.in.fname = fname;
1777 /* Test if a set-eof on pathname breaks an exclusive oplock. */
1778 torture_comment(tctx, "BATCH11: Test if setpathinfo set EOF breaks oplocks.\n");
1780 ZERO_STRUCT(break_info);
1782 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1783 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1784 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1785 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1786 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1787 NTCREATEX_SHARE_ACCESS_WRITE|
1788 NTCREATEX_SHARE_ACCESS_DELETE;
1789 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1790 status = smb_raw_open(cli1->tree, tctx, &io);
1791 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1792 fnum = io.ntcreatex.out.file.fnum;
1793 torture_wait_for_oplock_break(tctx);
1794 CHECK_VAL(break_info.count, 0);
1795 CHECK_VAL(break_info.failures, 0);
1796 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1799 sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1800 sfi.generic.in.file.path = fname;
1801 sfi.end_of_file_info.in.size = 100;
1803 status = smb_raw_setpathinfo(cli2->tree, &sfi);
1804 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1806 torture_wait_for_oplock_break(tctx);
1807 CHECK_VAL(break_info.count, get_setinfo_break_count(tctx));
1808 CHECK_VAL(break_info.failures, 0);
1809 CHECK_VAL(break_info.level, 0);
1811 smbcli_close(cli1->tree, fnum);
1814 smb_raw_exit(cli1->session);
1815 smb_raw_exit(cli2->session);
1816 smbcli_deltree(cli1->tree, BASEDIR);
1820 static bool test_raw_oplock_batch12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1822 const char *fname = BASEDIR "\\test_batch12.dat";
1826 union smb_setfileinfo sfi;
1829 if (!torture_setup_dir(cli1, BASEDIR)) {
1834 smbcli_unlink(cli1->tree, fname);
1836 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1839 base ntcreatex parms
1841 io.generic.level = RAW_OPEN_NTCREATEX;
1842 io.ntcreatex.in.root_fid.fnum = 0;
1843 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1844 io.ntcreatex.in.alloc_size = 0;
1845 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1846 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1847 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1848 io.ntcreatex.in.create_options = 0;
1849 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1850 io.ntcreatex.in.security_flags = 0;
1851 io.ntcreatex.in.fname = fname;
1853 /* Test if a set-allocation size on pathname breaks an exclusive oplock. */
1854 torture_comment(tctx, "BATCH12: Test if setpathinfo allocation size breaks oplocks.\n");
1856 ZERO_STRUCT(break_info);
1857 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1859 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1860 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1861 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1862 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1863 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1864 NTCREATEX_SHARE_ACCESS_WRITE|
1865 NTCREATEX_SHARE_ACCESS_DELETE;
1866 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1867 status = smb_raw_open(cli1->tree, tctx, &io);
1868 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1869 fnum = io.ntcreatex.out.file.fnum;
1870 torture_wait_for_oplock_break(tctx);
1871 CHECK_VAL(break_info.count, 0);
1872 CHECK_VAL(break_info.failures, 0);
1873 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1876 sfi.generic.level = SMB_SFILEINFO_ALLOCATION_INFORMATION;
1877 sfi.generic.in.file.path = fname;
1878 sfi.allocation_info.in.alloc_size = 65536 * 8;
1880 status = smb_raw_setpathinfo(cli2->tree, &sfi);
1881 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1883 torture_wait_for_oplock_break(tctx);
1884 CHECK_VAL(break_info.count, get_setinfo_break_count(tctx));
1885 CHECK_VAL(break_info.failures, 0);
1886 CHECK_VAL(break_info.level, 0);
1888 smbcli_close(cli1->tree, fnum);
1891 smb_raw_exit(cli1->session);
1892 smb_raw_exit(cli2->session);
1893 smbcli_deltree(cli1->tree, BASEDIR);
1897 static bool test_raw_oplock_batch13(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1899 const char *fname = BASEDIR "\\test_batch13.dat";
1903 uint16_t fnum=0, fnum2=0;
1905 if (!torture_setup_dir(cli1, BASEDIR)) {
1910 smbcli_unlink(cli1->tree, fname);
1912 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1913 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
1916 base ntcreatex parms
1918 io.generic.level = RAW_OPEN_NTCREATEX;
1919 io.ntcreatex.in.root_fid.fnum = 0;
1920 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1921 io.ntcreatex.in.alloc_size = 0;
1922 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1923 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1924 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1925 io.ntcreatex.in.create_options = 0;
1926 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1927 io.ntcreatex.in.security_flags = 0;
1928 io.ntcreatex.in.fname = fname;
1930 torture_comment(tctx, "BATCH13: open with batch oplock\n");
1931 ZERO_STRUCT(break_info);
1933 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1934 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1935 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1936 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1937 NTCREATEX_SHARE_ACCESS_WRITE|
1938 NTCREATEX_SHARE_ACCESS_DELETE;
1939 status = smb_raw_open(cli1->tree, tctx, &io);
1940 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1941 fnum = io.ntcreatex.out.file.fnum;
1942 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1944 ZERO_STRUCT(break_info);
1946 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE dispostion causes oplock break\n");
1948 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1949 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1950 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1951 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1952 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1953 NTCREATEX_SHARE_ACCESS_WRITE|
1954 NTCREATEX_SHARE_ACCESS_DELETE;
1955 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
1956 status = smb_raw_open(cli2->tree, tctx, &io);
1957 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1958 fnum2 = io.ntcreatex.out.file.fnum;
1959 torture_wait_for_oplock_break(tctx);
1960 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1961 CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
1962 CHECK_VAL(break_info.failures, 0);
1964 smbcli_close(cli1->tree, fnum);
1965 smbcli_close(cli2->tree, fnum2);
1968 smb_raw_exit(cli1->session);
1969 smb_raw_exit(cli2->session);
1970 smbcli_deltree(cli1->tree, BASEDIR);
1974 static bool test_raw_oplock_batch14(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1976 const char *fname = BASEDIR "\\test_batch14.dat";
1980 uint16_t fnum=0, fnum2=0;
1982 if (!torture_setup_dir(cli1, BASEDIR)) {
1987 smbcli_unlink(cli1->tree, fname);
1989 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1992 base ntcreatex parms
1994 io.generic.level = RAW_OPEN_NTCREATEX;
1995 io.ntcreatex.in.root_fid.fnum = 0;
1996 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1997 io.ntcreatex.in.alloc_size = 0;
1998 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1999 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2000 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2001 io.ntcreatex.in.create_options = 0;
2002 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2003 io.ntcreatex.in.security_flags = 0;
2004 io.ntcreatex.in.fname = fname;
2006 torture_comment(tctx, "BATCH14: open with batch oplock\n");
2007 ZERO_STRUCT(break_info);
2009 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2010 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2011 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2012 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2013 NTCREATEX_SHARE_ACCESS_WRITE|
2014 NTCREATEX_SHARE_ACCESS_DELETE;
2015 status = smb_raw_open(cli1->tree, tctx, &io);
2016 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2017 fnum = io.ntcreatex.out.file.fnum;
2018 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2020 ZERO_STRUCT(break_info);
2022 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_SUPERSEDE dispostion causes oplock break\n");
2024 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2025 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2026 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2027 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
2028 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2029 NTCREATEX_SHARE_ACCESS_WRITE|
2030 NTCREATEX_SHARE_ACCESS_DELETE;
2031 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
2032 status = smb_raw_open(cli2->tree, tctx, &io);
2033 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2034 fnum2 = io.ntcreatex.out.file.fnum;
2035 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2037 torture_wait_for_oplock_break(tctx);
2038 CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
2039 CHECK_VAL(break_info.failures, 0);
2041 smbcli_close(cli1->tree, fnum);
2042 smbcli_close(cli2->tree, fnum2);
2044 smb_raw_exit(cli1->session);
2045 smb_raw_exit(cli2->session);
2046 smbcli_deltree(cli1->tree, BASEDIR);
2050 static bool test_raw_oplock_batch15(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2052 const char *fname = BASEDIR "\\test_batch15.dat";
2056 union smb_fileinfo qfi;
2059 if (!torture_setup_dir(cli1, BASEDIR)) {
2064 smbcli_unlink(cli1->tree, fname);
2066 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2069 base ntcreatex parms
2071 io.generic.level = RAW_OPEN_NTCREATEX;
2072 io.ntcreatex.in.root_fid.fnum = 0;
2073 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2074 io.ntcreatex.in.alloc_size = 0;
2075 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2076 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2077 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2078 io.ntcreatex.in.create_options = 0;
2079 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2080 io.ntcreatex.in.security_flags = 0;
2081 io.ntcreatex.in.fname = fname;
2083 /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
2084 torture_comment(tctx, "BATCH15: Test if qpathinfo all info breaks a batch oplock (should not).\n");
2086 ZERO_STRUCT(break_info);
2088 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2089 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2090 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2091 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2092 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2093 NTCREATEX_SHARE_ACCESS_WRITE|
2094 NTCREATEX_SHARE_ACCESS_DELETE;
2095 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2096 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2097 status = smb_raw_open(cli1->tree, tctx, &io);
2098 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2099 fnum = io.ntcreatex.out.file.fnum;
2101 torture_wait_for_oplock_break(tctx);
2102 CHECK_VAL(break_info.count, 0);
2103 CHECK_VAL(break_info.failures, 0);
2104 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2107 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2108 qfi.generic.in.file.path = fname;
2110 status = smb_raw_pathinfo(cli2->tree, tctx, &qfi);
2111 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2113 torture_wait_for_oplock_break(tctx);
2114 CHECK_VAL(break_info.count, 0);
2116 smbcli_close(cli1->tree, fnum);
2119 smb_raw_exit(cli1->session);
2120 smb_raw_exit(cli2->session);
2121 smbcli_deltree(cli1->tree, BASEDIR);
2125 static bool test_raw_oplock_batch16(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2127 const char *fname = BASEDIR "\\test_batch16.dat";
2131 uint16_t fnum=0, fnum2=0;
2133 if (!torture_setup_dir(cli1, BASEDIR)) {
2138 smbcli_unlink(cli1->tree, fname);
2140 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2141 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
2144 base ntcreatex parms
2146 io.generic.level = RAW_OPEN_NTCREATEX;
2147 io.ntcreatex.in.root_fid.fnum = 0;
2148 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2149 io.ntcreatex.in.alloc_size = 0;
2150 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2151 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2152 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2153 io.ntcreatex.in.create_options = 0;
2154 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2155 io.ntcreatex.in.security_flags = 0;
2156 io.ntcreatex.in.fname = fname;
2158 torture_comment(tctx, "BATCH16: open with batch oplock\n");
2159 ZERO_STRUCT(break_info);
2161 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2162 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2163 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2164 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2165 NTCREATEX_SHARE_ACCESS_WRITE|
2166 NTCREATEX_SHARE_ACCESS_DELETE;
2167 status = smb_raw_open(cli1->tree, tctx, &io);
2168 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2169 fnum = io.ntcreatex.out.file.fnum;
2170 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2172 ZERO_STRUCT(break_info);
2174 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
2176 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2177 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2178 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2179 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
2180 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2181 NTCREATEX_SHARE_ACCESS_WRITE|
2182 NTCREATEX_SHARE_ACCESS_DELETE;
2183 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2184 status = smb_raw_open(cli2->tree, tctx, &io);
2185 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2186 fnum2 = io.ntcreatex.out.file.fnum;
2187 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2189 torture_wait_for_oplock_break(tctx);
2190 CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
2191 CHECK_VAL(break_info.failures, 0);
2193 smbcli_close(cli1->tree, fnum);
2194 smbcli_close(cli2->tree, fnum2);
2197 smb_raw_exit(cli1->session);
2198 smb_raw_exit(cli2->session);
2199 smbcli_deltree(cli1->tree, BASEDIR);
2203 static bool test_raw_oplock_batch17(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2205 const char *fname1 = BASEDIR "\\test_batch17_1.dat";
2206 const char *fname2 = BASEDIR "\\test_batch17_2.dat";
2210 union smb_rename rn;
2213 if (!torture_setup_dir(cli1, BASEDIR)) {
2218 smbcli_unlink(cli1->tree, fname1);
2219 smbcli_unlink(cli1->tree, fname2);
2221 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2224 base ntcreatex parms
2226 io.generic.level = RAW_OPEN_NTCREATEX;
2227 io.ntcreatex.in.root_fid.fnum = 0;
2228 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2229 io.ntcreatex.in.alloc_size = 0;
2230 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2231 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2232 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2233 io.ntcreatex.in.create_options = 0;
2234 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2235 io.ntcreatex.in.security_flags = 0;
2236 io.ntcreatex.in.fname = fname1;
2238 torture_comment(tctx, "BATCH17: open a file with an batch oplock (share mode: none)\n");
2240 ZERO_STRUCT(break_info);
2241 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2242 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2243 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2245 status = smb_raw_open(cli1->tree, tctx, &io);
2246 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2247 fnum = io.ntcreatex.out.file.fnum;
2248 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2250 torture_comment(tctx, "rename should trigger a break\n");
2252 rn.generic.level = RAW_RENAME_RENAME;
2253 rn.rename.in.pattern1 = fname1;
2254 rn.rename.in.pattern2 = fname2;
2255 rn.rename.in.attrib = 0;
2257 torture_comment(tctx, "trying rename while first file open\n");
2258 status = smb_raw_rename(cli2->tree, &rn);
2259 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2261 torture_wait_for_oplock_break(tctx);
2262 CHECK_VAL(break_info.count, 1);
2263 CHECK_VAL(break_info.failures, 0);
2264 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2266 smbcli_close(cli1->tree, fnum);
2269 smb_raw_exit(cli1->session);
2270 smb_raw_exit(cli2->session);
2271 smbcli_deltree(cli1->tree, BASEDIR);
2275 static bool test_raw_oplock_batch18(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2277 const char *fname1 = BASEDIR "\\test_batch18_1.dat";
2278 const char *fname2 = BASEDIR "\\test_batch18_2.dat";
2282 union smb_rename rn;
2285 if (!torture_setup_dir(cli1, BASEDIR)) {
2290 smbcli_unlink(cli1->tree, fname1);
2291 smbcli_unlink(cli1->tree, fname2);
2293 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2296 base ntcreatex parms
2298 io.generic.level = RAW_OPEN_NTCREATEX;
2299 io.ntcreatex.in.root_fid.fnum = 0;
2300 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2301 io.ntcreatex.in.alloc_size = 0;
2302 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2303 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2304 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2305 io.ntcreatex.in.create_options = 0;
2306 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2307 io.ntcreatex.in.security_flags = 0;
2308 io.ntcreatex.in.fname = fname1;
2310 torture_comment(tctx, "BATCH18: open a file with an batch oplock (share mode: none)\n");
2312 ZERO_STRUCT(break_info);
2313 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2314 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2315 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2317 status = smb_raw_open(cli1->tree, tctx, &io);
2318 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2319 fnum = io.ntcreatex.out.file.fnum;
2320 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2322 torture_comment(tctx, "ntrename should trigger a break\n");
2324 rn.generic.level = RAW_RENAME_NTRENAME;
2325 rn.ntrename.in.attrib = 0;
2326 rn.ntrename.in.flags = RENAME_FLAG_RENAME;
2327 rn.ntrename.in.old_name = fname1;
2328 rn.ntrename.in.new_name = fname2;
2329 torture_comment(tctx, "trying rename while first file open\n");
2330 status = smb_raw_rename(cli2->tree, &rn);
2331 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2333 torture_wait_for_oplock_break(tctx);
2334 CHECK_VAL(break_info.count, 1);
2335 CHECK_VAL(break_info.failures, 0);
2336 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2338 smbcli_close(cli1->tree, fnum);
2341 smb_raw_exit(cli1->session);
2342 smb_raw_exit(cli2->session);
2343 smbcli_deltree(cli1->tree, BASEDIR);
2347 static bool test_raw_oplock_batch19(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2349 const char *fname1 = BASEDIR "\\test_batch19_1.dat";
2350 const char *fname2 = BASEDIR "\\test_batch19_2.dat";
2351 const char *fname3 = BASEDIR "\\test_batch19_3.dat";
2355 union smb_fileinfo qfi;
2356 union smb_setfileinfo sfi;
2359 if (!torture_setup_dir(cli1, BASEDIR)) {
2364 smbcli_unlink(cli1->tree, fname1);
2365 smbcli_unlink(cli1->tree, fname2);
2366 smbcli_unlink(cli1->tree, fname3);
2368 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2371 base ntcreatex parms
2373 io.generic.level = RAW_OPEN_NTCREATEX;
2374 io.ntcreatex.in.root_fid.fnum = 0;
2375 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2376 io.ntcreatex.in.alloc_size = 0;
2377 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2378 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2379 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
2380 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2381 io.ntcreatex.in.create_options = 0;
2382 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2383 io.ntcreatex.in.security_flags = 0;
2384 io.ntcreatex.in.fname = fname1;
2386 torture_comment(tctx, "BATCH19: open a file with an batch oplock (share mode: none)\n");
2387 ZERO_STRUCT(break_info);
2388 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2389 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2390 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2391 status = smb_raw_open(cli1->tree, tctx, &io);
2392 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2393 fnum = io.ntcreatex.out.file.fnum;
2394 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2396 torture_comment(tctx, "setpathinfo rename info should trigger a break "
2399 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2400 sfi.generic.in.file.path = fname1;
2401 sfi.rename_information.in.overwrite = 0;
2402 sfi.rename_information.in.root_fid = 0;
2403 sfi.rename_information.in.new_name = fname2+strlen(BASEDIR)+1;
2405 status = smb_raw_setpathinfo(cli2->tree, &sfi);
2406 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2408 torture_wait_for_oplock_break(tctx);
2410 CHECK_VAL(break_info.failures, 0);
2412 if (TARGET_IS_WINXP(tctx) || TARGET_IS_W2K12(tctx)) {
2413 /* Win XP breaks to level2. */
2414 CHECK_VAL(break_info.count, 1);
2415 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2416 } else if (TARGET_IS_W2K3(tctx) || TARGET_IS_W2K8(tctx) ||
2417 TARGET_IS_SAMBA3(tctx) || TARGET_IS_SAMBA4(tctx)) {
2418 /* Win2K3/2k8 incorrectly doesn't break at all. */
2419 CHECK_VAL(break_info.count, 0);
2421 /* win7/2k8r2 break to none. */
2422 CHECK_VAL(break_info.count, 1);
2423 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
2427 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2428 qfi.generic.in.file.fnum = fnum;
2430 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2431 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2432 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2434 /* Close and re-open file with oplock. */
2435 smbcli_close(cli1->tree, fnum);
2436 status = smb_raw_open(cli1->tree, tctx, &io);
2437 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2438 fnum = io.ntcreatex.out.file.fnum;
2439 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2441 torture_comment(tctx, "setfileinfo rename info on a client's own fid "
2442 "should not trigger a break nor a violation\n");
2443 ZERO_STRUCT(break_info);
2445 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2446 sfi.generic.in.file.fnum = fnum;
2447 sfi.rename_information.in.overwrite = 0;
2448 sfi.rename_information.in.root_fid = 0;
2449 sfi.rename_information.in.new_name = fname3+strlen(BASEDIR)+1;
2451 status = smb_raw_setfileinfo(cli1->tree, &sfi);
2452 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2454 torture_wait_for_oplock_break(tctx);
2455 if (TARGET_IS_WINXP(tctx)) {
2456 /* XP incorrectly breaks to level2. */
2457 CHECK_VAL(break_info.count, 1);
2458 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2460 CHECK_VAL(break_info.count, 0);
2464 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2465 qfi.generic.in.file.fnum = fnum;
2467 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2468 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2469 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2472 smbcli_close(cli1->tree, fnum);
2473 smb_raw_exit(cli1->session);
2474 smb_raw_exit(cli2->session);
2475 smbcli_deltree(cli1->tree, BASEDIR);
2479 /****************************************************
2480 Called from raw-rename - we need oplock handling for
2481 this test so this is why it's in oplock.c, not rename.c
2482 ****************************************************/
2484 bool test_trans2rename(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2486 const char *fname1 = BASEDIR "\\test_trans2rename_1.dat";
2487 const char *fname2 = BASEDIR "\\test_trans2rename_2.dat";
2488 const char *fname3 = BASEDIR "\\test_trans2rename_3.dat";
2492 union smb_fileinfo qfi;
2493 union smb_setfileinfo sfi;
2496 if (!torture_setup_dir(cli1, BASEDIR)) {
2501 smbcli_unlink(cli1->tree, fname1);
2502 smbcli_unlink(cli1->tree, fname2);
2503 smbcli_unlink(cli1->tree, fname3);
2505 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2508 base ntcreatex parms
2510 io.generic.level = RAW_OPEN_NTCREATEX;
2511 io.ntcreatex.in.root_fid.fnum = 0;
2512 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2513 io.ntcreatex.in.alloc_size = 0;
2514 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2515 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2516 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
2517 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2518 io.ntcreatex.in.create_options = 0;
2519 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2520 io.ntcreatex.in.security_flags = 0;
2521 io.ntcreatex.in.fname = fname1;
2523 torture_comment(tctx, "open a file with an exclusive oplock (share mode: none)\n");
2524 ZERO_STRUCT(break_info);
2525 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2526 NTCREATEX_FLAGS_REQUEST_OPLOCK;
2527 status = smb_raw_open(cli1->tree, tctx, &io);
2528 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2529 fnum = io.ntcreatex.out.file.fnum;
2530 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
2532 torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
2534 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2535 sfi.generic.in.file.path = fname1;
2536 sfi.rename_information.in.overwrite = 0;
2537 sfi.rename_information.in.root_fid = 0;
2538 sfi.rename_information.in.new_name = fname2+strlen(BASEDIR)+1;
2540 status = smb_raw_setpathinfo(cli2->tree, &sfi);
2542 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2544 torture_wait_for_oplock_break(tctx);
2545 CHECK_VAL(break_info.count, 0);
2548 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2549 qfi.generic.in.file.fnum = fnum;
2551 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2552 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2553 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2555 torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
2557 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2558 sfi.generic.in.file.fnum = fnum;
2559 sfi.rename_information.in.overwrite = 0;
2560 sfi.rename_information.in.root_fid = 0;
2561 sfi.rename_information.in.new_name = fname3+strlen(BASEDIR)+1;
2563 status = smb_raw_setfileinfo(cli1->tree, &sfi);
2564 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2566 torture_wait_for_oplock_break(tctx);
2567 CHECK_VAL(break_info.count, 0);
2570 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2571 qfi.generic.in.file.fnum = fnum;
2573 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2574 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2575 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2578 smbcli_close(cli1->tree, fnum);
2579 smb_raw_exit(cli1->session);
2580 smb_raw_exit(cli2->session);
2581 smbcli_deltree(cli1->tree, BASEDIR);
2585 /****************************************************
2586 Called from raw-rename - we need oplock handling for
2587 this test so this is why it's in oplock.c, not rename.c
2588 ****************************************************/
2590 bool test_nttransrename(struct torture_context *tctx, struct smbcli_state *cli1)
2592 const char *fname1 = BASEDIR "\\test_nttransrename_1.dat";
2593 const char *fname2 = BASEDIR "\\test_nttransrename_2.dat";
2597 union smb_fileinfo qfi, qpi;
2598 union smb_rename rn;
2601 if (!torture_setup_dir(cli1, BASEDIR)) {
2606 smbcli_unlink(cli1->tree, fname1);
2607 smbcli_unlink(cli1->tree, fname2);
2609 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2612 base ntcreatex parms
2614 io.generic.level = RAW_OPEN_NTCREATEX;
2615 io.ntcreatex.in.root_fid.fnum = 0;
2616 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2617 io.ntcreatex.in.alloc_size = 0;
2618 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2619 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2620 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2621 io.ntcreatex.in.create_options = 0;
2622 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2623 io.ntcreatex.in.security_flags = 0;
2624 io.ntcreatex.in.fname = fname1;
2626 torture_comment(tctx, "nttrans_rename: open a file with an exclusive oplock (share mode: none)\n");
2627 ZERO_STRUCT(break_info);
2628 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2629 NTCREATEX_FLAGS_REQUEST_OPLOCK;
2630 status = smb_raw_open(cli1->tree, tctx, &io);
2631 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2632 fnum = io.ntcreatex.out.file.fnum;
2633 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
2635 torture_comment(tctx, "nttrans_rename: should not trigger a break nor a share mode violation\n");
2637 rn.generic.level = RAW_RENAME_NTTRANS;
2638 rn.nttrans.in.file.fnum = fnum;
2639 rn.nttrans.in.flags = 0;
2640 rn.nttrans.in.new_name = fname2+strlen(BASEDIR)+1;
2642 status = smb_raw_rename(cli1->tree, &rn);
2643 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2645 torture_wait_for_oplock_break(tctx);
2646 CHECK_VAL(break_info.count, 0);
2648 /* w2k3 does nothing, it doesn't rename the file */
2649 torture_comment(tctx, "nttrans_rename: the server should have done nothing\n");
2651 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2652 qfi.generic.in.file.fnum = fnum;
2654 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2655 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2656 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname1);
2659 qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2660 qpi.generic.in.file.path = fname1;
2662 status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2663 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2664 CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1);
2667 qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2668 qpi.generic.in.file.path = fname2;
2670 status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2671 CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2673 torture_comment(tctx, "nttrans_rename: after closing the file the file is still not renamed\n");
2674 status = smbcli_close(cli1->tree, fnum);
2675 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2678 qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2679 qpi.generic.in.file.path = fname1;
2681 status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2682 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2683 CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1);
2686 qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2687 qpi.generic.in.file.path = fname2;
2689 status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2690 CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2692 torture_comment(tctx, "nttrans_rename: rename with an invalid handle gives NT_STATUS_INVALID_HANDLE\n");
2694 rn.generic.level = RAW_RENAME_NTTRANS;
2695 rn.nttrans.in.file.fnum = fnum+1;
2696 rn.nttrans.in.flags = 0;
2697 rn.nttrans.in.new_name = fname2+strlen(BASEDIR)+1;
2699 status = smb_raw_rename(cli1->tree, &rn);
2701 CHECK_STATUS(tctx, status, NT_STATUS_INVALID_HANDLE);
2704 smb_raw_exit(cli1->session);
2705 smbcli_deltree(cli1->tree, BASEDIR);
2710 static bool test_raw_oplock_batch20(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2712 const char *fname1 = BASEDIR "\\test_batch20_1.dat";
2713 const char *fname2 = BASEDIR "\\test_batch20_2.dat";
2714 const char *fname3 = BASEDIR "\\test_batch20_3.dat";
2718 union smb_fileinfo qfi;
2719 union smb_setfileinfo sfi;
2720 uint16_t fnum=0,fnum2=0;
2722 if (!torture_setup_dir(cli1, BASEDIR)) {
2727 smbcli_unlink(cli1->tree, fname1);
2728 smbcli_unlink(cli1->tree, fname2);
2729 smbcli_unlink(cli1->tree, fname3);
2731 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2734 base ntcreatex parms
2736 io.generic.level = RAW_OPEN_NTCREATEX;
2737 io.ntcreatex.in.root_fid.fnum = 0;
2738 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2739 io.ntcreatex.in.alloc_size = 0;
2740 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2741 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2742 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2743 io.ntcreatex.in.create_options = 0;
2744 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2745 io.ntcreatex.in.security_flags = 0;
2746 io.ntcreatex.in.fname = fname1;
2748 torture_comment(tctx, "BATCH20: open a file with an batch oplock (share mode: all)\n");
2749 ZERO_STRUCT(break_info);
2750 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2751 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2752 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2753 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2754 NTCREATEX_SHARE_ACCESS_WRITE|
2755 NTCREATEX_SHARE_ACCESS_DELETE;
2756 status = smb_raw_open(cli1->tree, tctx, &io);
2757 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2758 fnum = io.ntcreatex.out.file.fnum;
2759 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2762 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2763 sfi.generic.in.file.path = fname1;
2764 sfi.rename_information.in.overwrite = 0;
2765 sfi.rename_information.in.root_fid = 0;
2766 sfi.rename_information.in.new_name = fname2+strlen(BASEDIR)+1;
2768 status = smb_raw_setpathinfo(cli2->tree, &sfi);
2769 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2771 torture_wait_for_oplock_break(tctx);
2772 CHECK_VAL(break_info.failures, 0);
2774 if (TARGET_IS_WINXP(tctx) || TARGET_IS_W2K12(tctx)) {
2775 /* Win XP breaks to level2. */
2776 CHECK_VAL(break_info.count, 1);
2777 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2778 } else if (TARGET_IS_W2K3(tctx) || TARGET_IS_W2K8(tctx) ||
2779 TARGET_IS_SAMBA3(tctx) || TARGET_IS_SAMBA4(tctx)) {
2780 /* Win2K3/2k8 incorrectly doesn't break at all. */
2781 CHECK_VAL(break_info.count, 0);
2783 /* win7/2k8r2 break to none. */
2784 CHECK_VAL(break_info.count, 1);
2785 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
2789 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2790 qfi.generic.in.file.fnum = fnum;
2792 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2793 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2794 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2796 torture_comment(tctx, "open a file with the new name an batch oplock (share mode: all)\n");
2797 ZERO_STRUCT(break_info);
2798 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2799 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2800 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2801 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2802 NTCREATEX_SHARE_ACCESS_WRITE|
2803 NTCREATEX_SHARE_ACCESS_DELETE;
2804 io.ntcreatex.in.fname = fname2;
2805 status = smb_raw_open(cli2->tree, tctx, &io);
2806 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2807 fnum2 = io.ntcreatex.out.file.fnum;
2808 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2810 torture_wait_for_oplock_break(tctx);
2812 if (TARGET_IS_WINXP(tctx)) {
2813 /* XP broke to level2, and doesn't break again. */
2814 CHECK_VAL(break_info.count, 0);
2815 } else if (TARGET_IS_W2K3(tctx) || TARGET_IS_W2K8(tctx) ||
2816 TARGET_IS_SAMBA3(tctx) || TARGET_IS_SAMBA4(tctx)) {
2817 /* Win2K3 incorrectly didn't break before so break now. */
2818 CHECK_VAL(break_info.count, 1);
2819 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2821 /* win7/2k8r2 broke to none, and doesn't break again. */
2822 CHECK_VAL(break_info.count, 0);
2825 ZERO_STRUCT(break_info);
2828 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2829 sfi.generic.in.file.fnum = fnum;
2830 sfi.rename_information.in.overwrite = 0;
2831 sfi.rename_information.in.root_fid = 0;
2832 sfi.rename_information.in.new_name = fname3+strlen(BASEDIR)+1;
2834 status = smb_raw_setfileinfo(cli1->tree, &sfi);
2835 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2837 torture_wait_for_oplock_break(tctx);
2838 CHECK_VAL(break_info.count, 0);
2841 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2842 qfi.generic.in.file.fnum = fnum;
2844 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2845 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2846 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2849 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2850 qfi.generic.in.file.fnum = fnum2;
2852 status = smb_raw_fileinfo(cli2->tree, tctx, &qfi);
2853 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2854 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2858 smbcli_close(cli1->tree, fnum);
2859 smbcli_close(cli2->tree, fnum2);
2860 smb_raw_exit(cli1->session);
2861 smb_raw_exit(cli2->session);
2862 smbcli_deltree(cli1->tree, BASEDIR);
2866 static bool test_raw_oplock_batch21(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2868 const char *fname = BASEDIR "\\test_batch21.dat";
2877 if (!torture_setup_dir(cli1, BASEDIR)) {
2882 smbcli_unlink(cli1->tree, fname);
2884 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2887 base ntcreatex parms
2889 io.generic.level = RAW_OPEN_NTCREATEX;
2890 io.ntcreatex.in.root_fid.fnum = 0;
2891 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2892 io.ntcreatex.in.alloc_size = 0;
2893 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2894 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2895 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2896 io.ntcreatex.in.create_options = 0;
2897 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2898 io.ntcreatex.in.security_flags = 0;
2899 io.ntcreatex.in.fname = fname;
2902 with a batch oplock we get a break
2904 torture_comment(tctx, "BATCH21: open with batch oplock\n");
2905 ZERO_STRUCT(break_info);
2906 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2907 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2908 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2909 status = smb_raw_open(cli1->tree, tctx, &io);
2910 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2911 fnum = io.ntcreatex.out.file.fnum;
2912 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2914 torture_comment(tctx, "writing should not generate a break\n");
2915 wr = smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
2917 CHECK_STATUS(tctx, smbcli_nt_error(cli1->tree), NT_STATUS_OK);
2920 e.in.repeat_count = 1;
2921 status = smb_raw_echo(cli1->transport, &e);
2922 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2924 torture_wait_for_oplock_break(tctx);
2925 CHECK_VAL(break_info.count, 0);
2927 smbcli_close(cli1->tree, fnum);
2930 smb_raw_exit(cli1->session);
2931 smb_raw_exit(cli2->session);
2932 smbcli_deltree(cli1->tree, BASEDIR);
2936 static bool test_raw_oplock_batch22(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2938 const char *fname = BASEDIR "\\test_batch22.dat";
2942 uint16_t fnum = 0, fnum2 = 0, fnum3 = 0;
2944 int timeout = torture_setting_int(tctx, "oplocktimeout", 30);
2947 if (!torture_setup_dir(cli1, BASEDIR)) {
2952 smbcli_unlink(cli1->tree, fname);
2954 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2956 base ntcreatex parms
2958 io.generic.level = RAW_OPEN_NTCREATEX;
2959 io.ntcreatex.in.root_fid.fnum = 0;
2960 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2961 io.ntcreatex.in.alloc_size = 0;
2962 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2963 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2964 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2965 io.ntcreatex.in.create_options = 0;
2966 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2967 io.ntcreatex.in.security_flags = 0;
2968 io.ntcreatex.in.fname = fname;
2971 with a batch oplock we get a break
2973 torture_comment(tctx, "BATCH22: open with batch oplock\n");
2974 ZERO_STRUCT(break_info);
2975 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2976 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2977 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2978 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2979 NTCREATEX_SHARE_ACCESS_WRITE|
2980 NTCREATEX_SHARE_ACCESS_DELETE;
2981 status = smb_raw_open(cli1->tree, tctx, &io);
2982 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2983 fnum = io.ntcreatex.out.file.fnum;
2984 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2986 torture_comment(tctx, "a 2nd open should not succeed after the oplock "
2988 tv = timeval_current();
2989 smbcli_oplock_handler(cli1->transport, oplock_handler_timeout, cli1->tree);
2990 status = smb_raw_open(cli1->tree, tctx, &io);
2992 if (TARGET_IS_W2K3(tctx)) {
2993 /* 2k3 has an issue here. xp/win7 are ok. */
2994 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2996 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2999 fnum2 = io.ntcreatex.out.file.fnum;
3001 torture_wait_for_oplock_break(tctx);
3002 te = (int)timeval_elapsed(&tv);
3005 * Some servers detect clients that let oplocks timeout, so this check
3006 * only shows a warning message instead failing the test to eliminate
3007 * failures from repeated runs of the test. This isn't ideal, but
3008 * it's better than not running the test at all.
3010 CHECK_RANGE(te, timeout - 1, timeout + 15);
3012 CHECK_VAL(break_info.count, 1);
3013 CHECK_VAL(break_info.fnum, fnum);
3014 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3015 CHECK_VAL(break_info.failures, 0);
3016 ZERO_STRUCT(break_info);
3018 torture_comment(tctx, "a 2nd open should succeed after the oplock "
3019 "release without break\n");
3020 tv = timeval_current();
3021 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3022 status = smb_raw_open(cli1->tree, tctx, &io);
3023 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3025 /* Samba 3.6.0 and above behave as Windows. */
3026 if (TARGET_IS_SAMBA3(tctx)) {
3027 /* samba3 doesn't grant additional oplocks to bad clients. */
3028 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
3030 CHECK_VAL(io.ntcreatex.out.oplock_level,
3031 LEVEL_II_OPLOCK_RETURN);
3034 CHECK_VAL(io.ntcreatex.out.oplock_level,
3035 LEVEL_II_OPLOCK_RETURN);
3037 torture_wait_for_oplock_break(tctx);
3038 te = (int)timeval_elapsed(&tv);
3039 /* it should come in without delay */
3040 CHECK_RANGE(te+1, 0, timeout);
3041 fnum3 = io.ntcreatex.out.file.fnum;
3043 CHECK_VAL(break_info.count, 0);
3045 smbcli_close(cli1->tree, fnum);
3046 smbcli_close(cli1->tree, fnum2);
3047 smbcli_close(cli1->tree, fnum3);
3050 smb_raw_exit(cli1->session);
3051 smb_raw_exit(cli2->session);
3052 smbcli_deltree(cli1->tree, BASEDIR);
3056 static bool test_raw_oplock_batch23(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
3058 const char *fname = BASEDIR "\\test_batch23.dat";
3062 uint16_t fnum=0, fnum2=0,fnum3=0;
3063 struct smbcli_state *cli3 = NULL;
3065 if (!torture_setup_dir(cli1, BASEDIR)) {
3070 smbcli_unlink(cli1->tree, fname);
3072 ret = open_connection_no_level2_oplocks(tctx, &cli3);
3073 CHECK_VAL(ret, true);
3075 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3076 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
3077 smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
3080 base ntcreatex parms
3082 io.generic.level = RAW_OPEN_NTCREATEX;
3083 io.ntcreatex.in.root_fid.fnum = 0;
3084 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3085 io.ntcreatex.in.alloc_size = 0;
3086 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3087 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3088 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3089 io.ntcreatex.in.create_options = 0;
3090 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3091 io.ntcreatex.in.security_flags = 0;
3092 io.ntcreatex.in.fname = fname;
3094 torture_comment(tctx, "BATCH23: a open and ask for a batch oplock\n");
3095 ZERO_STRUCT(break_info);
3097 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
3098 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
3099 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3100 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3101 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3102 status = smb_raw_open(cli1->tree, tctx, &io);
3103 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3104 fnum = io.ntcreatex.out.file.fnum;
3105 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3107 ZERO_STRUCT(break_info);
3109 torture_comment(tctx, "a 2nd open without level2 oplock support should generate a break to level2\n");
3110 status = smb_raw_open(cli3->tree, tctx, &io);
3111 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3112 fnum3 = io.ntcreatex.out.file.fnum;
3113 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
3115 torture_wait_for_oplock_break(tctx);
3116 CHECK_VAL(break_info.count, 1);
3117 CHECK_VAL(break_info.fnum, fnum);
3118 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3119 CHECK_VAL(break_info.failures, 0);
3121 ZERO_STRUCT(break_info);
3123 torture_comment(tctx, "a 3rd open with level2 oplock support should not generate a break\n");
3124 status = smb_raw_open(cli2->tree, tctx, &io);
3125 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3126 fnum2 = io.ntcreatex.out.file.fnum;
3127 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
3129 torture_wait_for_oplock_break(tctx);
3130 CHECK_VAL(break_info.count, 0);
3132 smbcli_close(cli1->tree, fnum);
3133 smbcli_close(cli2->tree, fnum2);
3134 smbcli_close(cli3->tree, fnum3);
3137 smb_raw_exit(cli1->session);
3138 smb_raw_exit(cli2->session);
3139 smb_raw_exit(cli3->session);
3140 smbcli_deltree(cli1->tree, BASEDIR);
3144 static bool test_raw_oplock_batch24(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
3146 const char *fname = BASEDIR "\\test_batch24.dat";
3150 uint16_t fnum2=0,fnum3=0;
3151 struct smbcli_state *cli3 = NULL;
3153 if (!torture_setup_dir(cli1, BASEDIR)) {
3158 smbcli_unlink(cli1->tree, fname);
3160 ret = open_connection_no_level2_oplocks(tctx, &cli3);
3161 CHECK_VAL(ret, true);
3163 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3164 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
3165 smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
3168 base ntcreatex parms
3170 io.generic.level = RAW_OPEN_NTCREATEX;
3171 io.ntcreatex.in.root_fid.fnum = 0;
3172 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3173 io.ntcreatex.in.alloc_size = 0;
3174 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3175 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3176 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3177 io.ntcreatex.in.create_options = 0;
3178 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3179 io.ntcreatex.in.security_flags = 0;
3180 io.ntcreatex.in.fname = fname;
3182 torture_comment(tctx, "BATCH24: a open without level support and ask for a batch oplock\n");
3183 ZERO_STRUCT(break_info);
3185 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
3186 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
3187 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3188 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3189 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3190 status = smb_raw_open(cli3->tree, tctx, &io);
3191 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3192 fnum3 = io.ntcreatex.out.file.fnum;
3193 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3195 ZERO_STRUCT(break_info);
3197 torture_comment(tctx, "a 2nd open with level2 oplock support should generate a break to none\n");
3198 status = smb_raw_open(cli2->tree, tctx, &io);
3199 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3200 fnum2 = io.ntcreatex.out.file.fnum;
3201 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
3203 torture_wait_for_oplock_break(tctx);
3204 CHECK_VAL(break_info.count, 1);
3205 CHECK_VAL(break_info.fnum, fnum3);
3206 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
3207 CHECK_VAL(break_info.failures, 0);
3209 smbcli_close(cli3->tree, fnum3);
3210 smbcli_close(cli2->tree, fnum2);
3213 smb_raw_exit(cli1->session);
3214 smb_raw_exit(cli2->session);
3215 smb_raw_exit(cli3->session);
3216 smbcli_deltree(cli1->tree, BASEDIR);
3220 static bool test_raw_oplock_batch25(struct torture_context *tctx,
3221 struct smbcli_state *cli1,
3222 struct smbcli_state *cli2)
3224 const char *fname = BASEDIR "\\test_batch25.dat";
3228 union smb_setfileinfo sfi;
3231 if (!torture_setup_dir(cli1, BASEDIR)) {
3236 smbcli_unlink(cli1->tree, fname);
3238 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3241 base ntcreatex parms
3243 io.generic.level = RAW_OPEN_NTCREATEX;
3244 io.ntcreatex.in.root_fid.fnum = 0;
3245 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3246 io.ntcreatex.in.alloc_size = 0;
3247 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3248 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3249 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3250 io.ntcreatex.in.create_options = 0;
3251 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3252 io.ntcreatex.in.security_flags = 0;
3253 io.ntcreatex.in.fname = fname;
3255 torture_comment(tctx, "BATCH25: open a file with an batch oplock "
3256 "(share mode: none)\n");
3258 ZERO_STRUCT(break_info);
3259 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3260 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3261 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3262 status = smb_raw_open(cli1->tree, tctx, &io);
3263 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3264 fnum = io.ntcreatex.out.file.fnum;
3265 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3267 torture_comment(tctx, "setpathinfo attribute info should not trigger "
3268 "a break nor a violation\n");
3270 sfi.generic.level = RAW_SFILEINFO_SETATTR;
3271 sfi.generic.in.file.path = fname;
3272 sfi.setattr.in.attrib = FILE_ATTRIBUTE_HIDDEN;
3273 sfi.setattr.in.write_time = 0;
3275 status = smb_raw_setpathinfo(cli2->tree, &sfi);
3276 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3278 torture_wait_for_oplock_break(tctx);
3279 CHECK_VAL(break_info.count, 0);
3281 smbcli_close(cli1->tree, fnum);
3284 smb_raw_exit(cli1->session);
3285 smb_raw_exit(cli2->session);
3286 smbcli_deltree(cli1->tree, BASEDIR);
3291 * Similar to batch17/18, but test with open share mode rather than
3294 static bool test_raw_oplock_batch26(struct torture_context *tctx,
3295 struct smbcli_state *cli1, struct smbcli_state *cli2)
3297 const char *fname1 = BASEDIR "\\test_batch26_1.dat";
3298 const char *fname2 = BASEDIR "\\test_batch26_2.dat";
3302 union smb_rename rn;
3305 if (!torture_setup_dir(cli1, BASEDIR)) {
3310 smbcli_unlink(cli1->tree, fname1);
3311 smbcli_unlink(cli1->tree, fname2);
3313 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3317 base ntcreatex parms
3319 io.generic.level = RAW_OPEN_NTCREATEX;
3320 io.ntcreatex.in.root_fid.fnum = 0;
3321 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3322 io.ntcreatex.in.alloc_size = 0;
3323 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3324 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3325 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
3326 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3327 io.ntcreatex.in.create_options = 0;
3328 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3329 io.ntcreatex.in.security_flags = 0;
3330 io.ntcreatex.in.fname = fname1;
3332 torture_comment(tctx, "BATCH26: open a file with an batch oplock "
3333 "(share mode: none)\n");
3335 ZERO_STRUCT(break_info);
3336 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3337 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3338 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3341 status = smb_raw_open(cli1->tree, tctx, &io);
3342 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3343 fnum = io.ntcreatex.out.file.fnum;
3344 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3346 torture_comment(tctx, "rename should trigger a break\n");
3348 rn.generic.level = RAW_RENAME_RENAME;
3349 rn.rename.in.pattern1 = fname1;
3350 rn.rename.in.pattern2 = fname2;
3351 rn.rename.in.attrib = 0;
3353 torture_comment(tctx, "trying rename while first file open\n");
3354 status = smb_raw_rename(cli2->tree, &rn);
3355 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
3357 torture_wait_for_oplock_break(tctx);
3358 CHECK_VAL(break_info.count, 1);
3359 CHECK_VAL(break_info.failures, 0);
3360 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3362 /* Close and reopen with batch again. */
3363 smbcli_close(cli1->tree, fnum);
3364 ZERO_STRUCT(break_info);
3366 status = smb_raw_open(cli1->tree, tctx, &io);
3367 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3368 fnum = io.ntcreatex.out.file.fnum;
3369 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3371 /* Now try ntrename. */
3372 torture_comment(tctx, "ntrename should trigger a break\n");
3374 rn.generic.level = RAW_RENAME_NTRENAME;
3375 rn.ntrename.in.attrib = 0;
3376 rn.ntrename.in.flags = RENAME_FLAG_RENAME;
3377 rn.ntrename.in.old_name = fname1;
3378 rn.ntrename.in.new_name = fname2;
3379 torture_comment(tctx, "trying rename while first file open\n");
3380 status = smb_raw_rename(cli2->tree, &rn);
3381 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
3383 torture_wait_for_oplock_break(tctx);
3384 CHECK_VAL(break_info.count, 1);
3385 CHECK_VAL(break_info.failures, 0);
3386 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3388 smbcli_close(cli1->tree, fnum);
3391 smb_raw_exit(cli1->session);
3392 smb_raw_exit(cli2->session);
3393 smbcli_deltree(cli1->tree, BASEDIR);
3397 /* Test how oplocks work on streams. */
3398 static bool test_raw_oplock_stream1(struct torture_context *tctx,
3399 struct smbcli_state *cli1,
3400 struct smbcli_state *cli2)
3404 const char *fname_base = BASEDIR "\\test_stream1.txt";
3405 const char *stream = "Stream One:$DATA";
3406 const char *fname_stream, *fname_default_stream;
3407 const char *default_stream = "::$DATA";
3411 int stream_fnum = -1;
3412 uint32_t batch_req = NTCREATEX_FLAGS_REQUEST_OPLOCK |
3413 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK | NTCREATEX_FLAGS_EXTENDED;
3414 uint32_t exclusive_req = NTCREATEX_FLAGS_REQUEST_OPLOCK |
3415 NTCREATEX_FLAGS_EXTENDED;
3417 #define NSTREAM_OPLOCK_RESULTS 8
3420 bool open_base_file;
3421 uint32_t oplock_req;
3422 uint32_t oplock_granted;
3423 } stream_oplock_results[NSTREAM_OPLOCK_RESULTS] = {
3424 /* Request oplock on stream without the base file open. */
3425 {&fname_stream, false, batch_req, NO_OPLOCK_RETURN},
3426 {&fname_default_stream, false, batch_req, NO_OPLOCK_RETURN},
3427 {&fname_stream, false, exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
3428 {&fname_default_stream, false, exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
3430 /* Request oplock on stream with the base file open. */
3431 {&fname_stream, true, batch_req, NO_OPLOCK_RETURN},
3432 {&fname_default_stream, true, batch_req, NO_OPLOCK_RETURN},
3433 {&fname_stream, true, exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
3434 {&fname_default_stream, true, exclusive_req, LEVEL_II_OPLOCK_RETURN},
3439 /* Only passes against windows at the moment. */
3440 if (torture_setting_bool(tctx, "samba3", false) ||
3441 torture_setting_bool(tctx, "samba4", false)) {
3442 torture_skip(tctx, "STREAM1 disabled against samba3+4\n");
3445 fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
3446 fname_default_stream = talloc_asprintf(tctx, "%s%s", fname_base,
3449 if (!torture_setup_dir(cli1, BASEDIR)) {
3452 smbcli_unlink(cli1->tree, fname_base);
3454 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3455 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
3457 /* Setup generic open parameters. */
3458 io.generic.level = RAW_OPEN_NTCREATEX;
3459 io.ntcreatex.in.root_fid.fnum = 0;
3460 io.ntcreatex.in.access_mask = (SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA|
3461 SEC_FILE_APPEND_DATA|SEC_STD_READ_CONTROL);
3462 io.ntcreatex.in.create_options = 0;
3463 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3464 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3465 NTCREATEX_SHARE_ACCESS_WRITE;
3466 io.ntcreatex.in.alloc_size = 0;
3467 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3468 io.ntcreatex.in.security_flags = 0;
3470 /* Create the file with a stream */
3471 io.ntcreatex.in.fname = fname_stream;
3472 io.ntcreatex.in.flags = 0;
3473 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
3474 status = smb_raw_open(cli1->tree, tctx, &io);
3475 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3476 smbcli_close(cli1->tree, io.ntcreatex.out.file.fnum);
3478 /* Change the disposition to open now that the file has been created. */
3479 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
3481 /* Try some permutations of taking oplocks on streams. */
3482 for (i = 0; i < NSTREAM_OPLOCK_RESULTS; i++) {
3483 const char *fname = *stream_oplock_results[i].fname;
3484 bool open_base_file = stream_oplock_results[i].open_base_file;
3485 uint32_t oplock_req = stream_oplock_results[i].oplock_req;
3486 uint32_t oplock_granted =
3487 stream_oplock_results[i].oplock_granted;
3490 if (open_base_file) {
3491 torture_comment(tctx, "Opening base file: %s with "
3492 "%d\n", fname_base, batch_req);
3493 io.ntcreatex.in.fname = fname_base;
3494 io.ntcreatex.in.flags = batch_req;
3495 status = smb_raw_open(cli2->tree, tctx, &io);
3496 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3497 CHECK_VAL(io.ntcreatex.out.oplock_level,
3498 BATCH_OPLOCK_RETURN);
3499 base_fnum = io.ntcreatex.out.file.fnum;
3502 torture_comment(tctx, "%d: Opening stream: %s with %d\n", i,
3504 io.ntcreatex.in.fname = fname;
3505 io.ntcreatex.in.flags = oplock_req;
3507 /* Do the open with the desired oplock on the stream. */
3508 status = smb_raw_open(cli1->tree, tctx, &io);
3509 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3510 CHECK_VAL(io.ntcreatex.out.oplock_level, oplock_granted);
3511 smbcli_close(cli1->tree, io.ntcreatex.out.file.fnum);
3513 /* Cleanup the base file if it was opened. */
3514 if (base_fnum != -1) {
3515 smbcli_close(cli2->tree, base_fnum);
3519 /* Open the stream with an exclusive oplock. */
3520 torture_comment(tctx, "Opening stream: %s with %d\n",
3521 fname_stream, exclusive_req);
3522 io.ntcreatex.in.fname = fname_stream;
3523 io.ntcreatex.in.flags = exclusive_req;
3524 status = smb_raw_open(cli1->tree, tctx, &io);
3525 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3526 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
3527 stream_fnum = io.ntcreatex.out.file.fnum;
3529 /* Open the base file and see if it contends. */
3530 ZERO_STRUCT(break_info);
3531 torture_comment(tctx, "Opening base file: %s with "
3532 "%d\n", fname_base, batch_req);
3533 io.ntcreatex.in.fname = fname_base;
3534 io.ntcreatex.in.flags = batch_req;
3535 status = smb_raw_open(cli2->tree, tctx, &io);
3536 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3537 CHECK_VAL(io.ntcreatex.out.oplock_level,
3538 BATCH_OPLOCK_RETURN);
3539 smbcli_close(cli2->tree, io.ntcreatex.out.file.fnum);
3541 torture_wait_for_oplock_break(tctx);
3542 CHECK_VAL(break_info.count, 0);
3543 CHECK_VAL(break_info.failures, 0);
3545 /* Open the stream again to see if it contends. */
3546 ZERO_STRUCT(break_info);
3547 torture_comment(tctx, "Opening stream again: %s with "
3548 "%d\n", fname_base, batch_req);
3549 io.ntcreatex.in.fname = fname_stream;
3550 io.ntcreatex.in.flags = exclusive_req;
3551 status = smb_raw_open(cli2->tree, tctx, &io);
3552 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3553 CHECK_VAL(io.ntcreatex.out.oplock_level,
3554 LEVEL_II_OPLOCK_RETURN);
3555 smbcli_close(cli2->tree, io.ntcreatex.out.file.fnum);
3557 torture_wait_for_oplock_break(tctx);
3558 CHECK_VAL(break_info.count, 1);
3559 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3560 CHECK_VAL(break_info.failures, 0);
3562 /* Close the stream. */
3563 if (stream_fnum != -1) {
3564 smbcli_close(cli1->tree, stream_fnum);
3568 smbcli_close(cli1->tree, fnum);
3569 smb_raw_exit(cli1->session);
3570 smb_raw_exit(cli2->session);
3571 smbcli_deltree(cli1->tree, BASEDIR);
3575 static bool test_raw_oplock_doc(struct torture_context *tctx,
3576 struct smbcli_state *cli)
3578 const char *fname = BASEDIR "\\test_oplock_doc.dat";
3584 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
3587 smbcli_unlink(cli->tree, fname);
3589 smbcli_oplock_handler(cli->transport, oplock_handler_ack_to_given,
3593 base ntcreatex parms
3595 io.generic.level = RAW_OPEN_NTCREATEX;
3596 io.ntcreatex.in.root_fid.fnum = 0;
3597 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3598 io.ntcreatex.in.alloc_size = 0;
3599 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3600 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3601 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3602 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
3603 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3604 io.ntcreatex.in.security_flags = 0;
3605 io.ntcreatex.in.fname = fname;
3607 torture_comment(tctx, "open a delete-on-close file with a batch "
3609 ZERO_STRUCT(break_info);
3610 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3611 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3612 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3614 status = smb_raw_open(cli->tree, tctx, &io);
3615 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3616 fnum = io.ntcreatex.out.file.fnum;
3617 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3619 smbcli_close(cli->tree, fnum);
3622 smb_raw_exit(cli->session);
3623 smbcli_deltree(cli->tree, BASEDIR);
3627 /* Open a file with a batch oplock, then open it again from a second client
3628 * requesting no oplock. Having two open file handles should break our own
3629 * oplock during BRL acquisition.
3631 static bool test_raw_oplock_brl1(struct torture_context *tctx,
3632 struct smbcli_state *cli1,
3633 struct smbcli_state *cli2)
3635 const char *fname = BASEDIR "\\test_batch_brl.dat";
3644 if (!torture_setup_dir(cli1, BASEDIR)) {
3649 smbcli_unlink(cli1->tree, fname);
3651 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3655 base ntcreatex parms
3657 io.generic.level = RAW_OPEN_NTCREATEX;
3658 io.ntcreatex.in.root_fid.fnum = 0;
3659 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3660 SEC_RIGHTS_FILE_WRITE;
3661 io.ntcreatex.in.alloc_size = 0;
3662 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3663 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3664 NTCREATEX_SHARE_ACCESS_WRITE;
3665 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3666 io.ntcreatex.in.create_options = 0;
3667 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3668 io.ntcreatex.in.security_flags = 0;
3669 io.ntcreatex.in.fname = fname;
3672 with a batch oplock we get a break
3674 torture_comment(tctx, "open with batch oplock\n");
3675 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3676 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3677 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3679 status = smb_raw_open(cli1->tree, tctx, &io);
3680 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3681 fnum = io.ntcreatex.out.file.fnum;
3682 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3683 /* create a file with bogus data */
3684 memset(buf, 0, sizeof(buf));
3686 if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
3689 torture_comment(tctx, "Failed to create file\n");
3693 torture_comment(tctx, "a 2nd open should give a break\n");
3694 ZERO_STRUCT(break_info);
3696 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
3697 status = smb_raw_open(cli2->tree, tctx, &io);
3698 fnum2 = io.ntcreatex.out.file.fnum;
3699 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3700 CHECK_VAL(break_info.count, 1);
3701 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3702 CHECK_VAL(break_info.failures, 0);
3703 CHECK_VAL(break_info.fnum, fnum);
3705 ZERO_STRUCT(break_info);
3707 torture_comment(tctx, "a self BRL acquisition should break to none\n");
3709 status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
3710 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3712 torture_wait_for_oplock_break(tctx);
3713 CHECK_VAL(break_info.count, 1);
3714 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
3715 CHECK_VAL(break_info.fnum, fnum);
3716 CHECK_VAL(break_info.failures, 0);
3718 /* expect no oplock break */
3719 ZERO_STRUCT(break_info);
3720 status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
3721 CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
3723 torture_wait_for_oplock_break(tctx);
3724 CHECK_VAL(break_info.count, 0);
3725 CHECK_VAL(break_info.level, 0);
3726 CHECK_VAL(break_info.fnum, 0);
3727 CHECK_VAL(break_info.failures, 0);
3729 smbcli_close(cli1->tree, fnum);
3730 smbcli_close(cli2->tree, fnum2);
3733 smb_raw_exit(cli1->session);
3734 smb_raw_exit(cli2->session);
3735 smbcli_deltree(cli1->tree, BASEDIR);
3740 /* Open a file with a batch oplock on one client and then acquire a brl.
3741 * We should not contend our own oplock.
3743 static bool test_raw_oplock_brl2(struct torture_context *tctx, struct smbcli_state *cli1)
3745 const char *fname = BASEDIR "\\test_batch_brl.dat";
3753 if (!torture_setup_dir(cli1, BASEDIR)) {
3758 smbcli_unlink(cli1->tree, fname);
3760 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3764 base ntcreatex parms
3766 io.generic.level = RAW_OPEN_NTCREATEX;
3767 io.ntcreatex.in.root_fid.fnum = 0;
3768 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3769 SEC_RIGHTS_FILE_WRITE;
3770 io.ntcreatex.in.alloc_size = 0;
3771 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3772 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3773 NTCREATEX_SHARE_ACCESS_WRITE;
3774 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3775 io.ntcreatex.in.create_options = 0;
3776 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3777 io.ntcreatex.in.security_flags = 0;
3778 io.ntcreatex.in.fname = fname;
3781 with a batch oplock we get a break
3783 torture_comment(tctx, "open with batch oplock\n");
3784 ZERO_STRUCT(break_info);
3785 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3786 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3787 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3789 status = smb_raw_open(cli1->tree, tctx, &io);
3790 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3791 fnum = io.ntcreatex.out.file.fnum;
3792 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3794 /* create a file with bogus data */
3795 memset(buf, 0, sizeof(buf));
3797 if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
3800 torture_comment(tctx, "Failed to create file\n");
3804 torture_comment(tctx, "a self BRL acquisition should not break to "
3807 status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
3808 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3810 status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
3811 CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
3813 /* With one file handle open a BRL should not contend our oplock.
3814 * Thus, no oplock break will be received and the entire break_info
3815 * struct will be 0 */
3816 torture_wait_for_oplock_break(tctx);
3817 CHECK_VAL(break_info.fnum, 0);
3818 CHECK_VAL(break_info.count, 0);
3819 CHECK_VAL(break_info.level, 0);
3820 CHECK_VAL(break_info.failures, 0);
3822 smbcli_close(cli1->tree, fnum);
3825 smb_raw_exit(cli1->session);
3826 smbcli_deltree(cli1->tree, BASEDIR);
3830 /* Open a file with a batch oplock twice from one client and then acquire a
3831 * brl. BRL acquisition should break our own oplock.
3833 static bool test_raw_oplock_brl3(struct torture_context *tctx,
3834 struct smbcli_state *cli1)
3836 const char *fname = BASEDIR "\\test_batch_brl.dat";
3844 if (!torture_setup_dir(cli1, BASEDIR)) {
3849 smbcli_unlink(cli1->tree, fname);
3851 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3855 base ntcreatex parms
3857 io.generic.level = RAW_OPEN_NTCREATEX;
3858 io.ntcreatex.in.root_fid.fnum = 0;
3859 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3860 SEC_RIGHTS_FILE_WRITE;
3861 io.ntcreatex.in.alloc_size = 0;
3862 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3863 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3864 NTCREATEX_SHARE_ACCESS_WRITE;
3865 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3866 io.ntcreatex.in.create_options = 0;
3867 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3868 io.ntcreatex.in.security_flags = 0;
3869 io.ntcreatex.in.fname = fname;
3872 with a batch oplock we get a break
3874 torture_comment(tctx, "open with batch oplock\n");
3875 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3876 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3877 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3879 status = smb_raw_open(cli1->tree, tctx, &io);
3880 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3881 fnum = io.ntcreatex.out.file.fnum;
3882 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3884 /* create a file with bogus data */
3885 memset(buf, 0, sizeof(buf));
3887 if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
3890 torture_comment(tctx, "Failed to create file\n");
3895 torture_comment(tctx, "a 2nd open should give a break\n");
3896 ZERO_STRUCT(break_info);
3898 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
3899 status = smb_raw_open(cli1->tree, tctx, &io);
3900 fnum2 = io.ntcreatex.out.file.fnum;
3901 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3902 CHECK_VAL(break_info.count, 1);
3903 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3904 CHECK_VAL(break_info.failures, 0);
3905 CHECK_VAL(break_info.fnum, fnum);
3907 ZERO_STRUCT(break_info);
3909 torture_comment(tctx, "a self BRL acquisition should break to none\n");
3911 status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
3912 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3914 torture_wait_for_oplock_break(tctx);
3915 CHECK_VAL(break_info.count, 1);
3916 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
3917 CHECK_VAL(break_info.fnum, fnum);
3918 CHECK_VAL(break_info.failures, 0);
3920 /* expect no oplock break */
3921 ZERO_STRUCT(break_info);
3922 status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
3923 CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
3925 torture_wait_for_oplock_break(tctx);
3926 CHECK_VAL(break_info.count, 0);
3927 CHECK_VAL(break_info.level, 0);
3928 CHECK_VAL(break_info.fnum, 0);
3929 CHECK_VAL(break_info.failures, 0);
3931 smbcli_close(cli1->tree, fnum);
3932 smbcli_close(cli1->tree, fnum2);
3935 smb_raw_exit(cli1->session);
3936 smbcli_deltree(cli1->tree, BASEDIR);
3941 * Open a file with an exclusive oplock from the 1st client and acquire a
3942 * brl. Then open the same file from the 2nd client that should give oplock
3943 * break with level2 to the 1st and return no oplock to the 2nd.
3945 static bool test_raw_oplock_brl4(struct torture_context *tctx,
3946 struct smbcli_state *cli1,
3947 struct smbcli_state *cli2)
3949 const char *fname = BASEDIR "\\test_batch_brl.dat";
3957 if (!torture_setup_dir(cli1, BASEDIR)) {
3962 smbcli_unlink(cli1->tree, fname);
3964 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3968 base ntcreatex parms
3970 io.generic.level = RAW_OPEN_NTCREATEX;
3971 io.ntcreatex.in.root_fid.fnum = 0;
3972 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3973 SEC_RIGHTS_FILE_WRITE;
3974 io.ntcreatex.in.alloc_size = 0;
3975 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3976 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3977 NTCREATEX_SHARE_ACCESS_WRITE;
3978 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3979 io.ntcreatex.in.create_options = 0;
3980 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3981 io.ntcreatex.in.security_flags = 0;
3982 io.ntcreatex.in.fname = fname;
3984 torture_comment(tctx, "open with exclusive oplock\n");
3985 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3986 NTCREATEX_FLAGS_REQUEST_OPLOCK;
3988 status = smb_raw_open(cli1->tree, tctx, &io);
3990 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3991 fnum = io.ntcreatex.out.file.fnum;
3992 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
3994 /* create a file with bogus data */
3995 memset(buf, 0, sizeof(buf));
3997 if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
4000 torture_comment(tctx, "Failed to create file\n");
4004 status = smbcli_lock(cli1->tree, fnum, 0, 1, 0, WRITE_LOCK);
4005 CHECK_STATUS(tctx, status, NT_STATUS_OK);
4007 torture_comment(tctx, "a 2nd open should give a break to the 1st\n");
4008 ZERO_STRUCT(break_info);
4010 status = smb_raw_open(cli2->tree, tctx, &io);
4012 CHECK_STATUS(tctx, status, NT_STATUS_OK);
4013 CHECK_VAL(break_info.count, 1);
4014 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
4015 CHECK_VAL(break_info.failures, 0);
4016 CHECK_VAL(break_info.fnum, fnum);
4018 torture_comment(tctx, "and return no oplock to the 2nd\n");
4019 fnum2 = io.ntcreatex.out.file.fnum;
4020 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
4022 smbcli_close(cli1->tree, fnum);
4023 smbcli_close(cli2->tree, fnum2);
4026 smb_raw_exit(cli1->session);
4027 smb_raw_exit(cli2->session);
4028 smbcli_deltree(cli1->tree, BASEDIR);
4033 basic testing of oplocks
4035 struct torture_suite *torture_raw_oplock(TALLOC_CTX *mem_ctx)
4037 struct torture_suite *suite = torture_suite_create(mem_ctx, "oplock");
4039 torture_suite_add_2smb_test(suite, "exclusive1", test_raw_oplock_exclusive1);
4040 torture_suite_add_2smb_test(suite, "exclusive2", test_raw_oplock_exclusive2);
4041 torture_suite_add_2smb_test(suite, "exclusive3", test_raw_oplock_exclusive3);
4042 torture_suite_add_2smb_test(suite, "exclusive4", test_raw_oplock_exclusive4);
4043 torture_suite_add_2smb_test(suite, "exclusive5", test_raw_oplock_exclusive5);
4044 torture_suite_add_2smb_test(suite, "exclusive6", test_raw_oplock_exclusive6);
4045 torture_suite_add_2smb_test(suite, "exclusive7", test_raw_oplock_exclusive7);
4046 torture_suite_add_2smb_test(suite, "exclusive8",
4047 test_raw_oplock_exclusive8);
4048 torture_suite_add_2smb_test(suite, "batch1", test_raw_oplock_batch1);
4049 torture_suite_add_2smb_test(suite, "batch2", test_raw_oplock_batch2);
4050 torture_suite_add_2smb_test(suite, "batch3", test_raw_oplock_batch3);
4051 torture_suite_add_2smb_test(suite, "batch4", test_raw_oplock_batch4);
4052 torture_suite_add_2smb_test(suite, "batch5", test_raw_oplock_batch5);
4053 torture_suite_add_2smb_test(suite, "batch6", test_raw_oplock_batch6);
4054 torture_suite_add_2smb_test(suite, "batch7", test_raw_oplock_batch7);
4055 torture_suite_add_2smb_test(suite, "batch8", test_raw_oplock_batch8);
4056 torture_suite_add_2smb_test(suite, "batch9", test_raw_oplock_batch9);
4057 torture_suite_add_2smb_test(suite, "batch10", test_raw_oplock_batch10);
4058 torture_suite_add_2smb_test(suite, "batch11", test_raw_oplock_batch11);
4059 torture_suite_add_2smb_test(suite, "batch12", test_raw_oplock_batch12);
4060 torture_suite_add_2smb_test(suite, "batch13", test_raw_oplock_batch13);
4061 torture_suite_add_2smb_test(suite, "batch14", test_raw_oplock_batch14);
4062 torture_suite_add_2smb_test(suite, "batch15", test_raw_oplock_batch15);
4063 torture_suite_add_2smb_test(suite, "batch16", test_raw_oplock_batch16);
4064 torture_suite_add_2smb_test(suite, "batch17", test_raw_oplock_batch17);
4065 torture_suite_add_2smb_test(suite, "batch18", test_raw_oplock_batch18);
4066 torture_suite_add_2smb_test(suite, "batch19", test_raw_oplock_batch19);
4067 torture_suite_add_2smb_test(suite, "batch20", test_raw_oplock_batch20);
4068 torture_suite_add_2smb_test(suite, "batch21", test_raw_oplock_batch21);
4069 torture_suite_add_2smb_test(suite, "batch22", test_raw_oplock_batch22);
4070 torture_suite_add_2smb_test(suite, "batch23", test_raw_oplock_batch23);
4071 torture_suite_add_2smb_test(suite, "batch24", test_raw_oplock_batch24);
4072 torture_suite_add_2smb_test(suite, "batch25", test_raw_oplock_batch25);
4073 torture_suite_add_2smb_test(suite, "batch26", test_raw_oplock_batch26);
4074 torture_suite_add_2smb_test(suite, "stream1", test_raw_oplock_stream1);
4075 torture_suite_add_1smb_test(suite, "doc1", test_raw_oplock_doc);
4076 torture_suite_add_2smb_test(suite, "brl1", test_raw_oplock_brl1);
4077 torture_suite_add_1smb_test(suite, "brl2", test_raw_oplock_brl2);
4078 torture_suite_add_1smb_test(suite, "brl3", test_raw_oplock_brl3);
4079 torture_suite_add_2smb_test(suite, "brl4", test_raw_oplock_brl4);
4085 stress testing of oplocks
4087 bool torture_bench_oplock(struct torture_context *torture)
4089 struct smbcli_state **cli;
4091 TALLOC_CTX *mem_ctx = talloc_new(torture);
4092 int torture_nprocs = torture_setting_int(torture, "nprocs", 4);
4094 int timelimit = torture_setting_int(torture, "timelimit", 10);
4098 cli = talloc_array(mem_ctx, struct smbcli_state *, torture_nprocs);
4100 torture_comment(torture, "Opening %d connections\n", torture_nprocs);
4101 for (i=0;i<torture_nprocs;i++) {
4102 if (!torture_open_connection_ev(&cli[i], i, torture, torture->ev)) {
4105 talloc_steal(mem_ctx, cli[i]);
4106 smbcli_oplock_handler(cli[i]->transport, oplock_handler_close,
4110 if (!torture_setup_dir(cli[0], BASEDIR)) {
4115 io.ntcreatex.level = RAW_OPEN_NTCREATEX;
4116 io.ntcreatex.in.root_fid.fnum = 0;
4117 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
4118 io.ntcreatex.in.alloc_size = 0;
4119 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
4120 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
4121 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
4122 io.ntcreatex.in.create_options = 0;
4123 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
4124 io.ntcreatex.in.security_flags = 0;
4125 io.ntcreatex.in.fname = BASEDIR "\\test.dat";
4126 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
4127 NTCREATEX_FLAGS_REQUEST_OPLOCK |
4128 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
4130 tv = timeval_current();
4133 we open the same file with SHARE_ACCESS_NONE from all the
4134 connections in a round robin fashion. Each open causes an
4135 oplock break on the previous connection, which is answered
4136 by the oplock_handler_close() to close the file.
4138 This measures how fast we can pass on oplocks, and stresses
4139 the oplock handling code
4141 torture_comment(torture, "Running for %d seconds\n", timelimit);
4142 while (timeval_elapsed(&tv) < timelimit) {
4143 for (i=0;i<torture_nprocs;i++) {
4146 status = smb_raw_open(cli[i]->tree, mem_ctx, &io);
4147 CHECK_STATUS(torture, status, NT_STATUS_OK);
4151 if (torture_setting_bool(torture, "progress", true)) {
4152 torture_comment(torture, "%.2f ops/second\r", count/timeval_elapsed(&tv));
4156 torture_comment(torture, "%.2f ops/second\n", count/timeval_elapsed(&tv));
4158 smb_raw_exit(cli[torture_nprocs-1]->session);
4161 smb_raw_exit(cli[0]->session);
4162 smbcli_deltree(cli[0]->tree, BASEDIR);
4163 talloc_free(mem_ctx);
4168 static struct hold_oplock_info {
4170 bool close_on_break;
4171 uint32_t share_access;
4174 { BASEDIR "\\notshared_close", true,
4175 NTCREATEX_SHARE_ACCESS_NONE, },
4176 { BASEDIR "\\notshared_noclose", false,
4177 NTCREATEX_SHARE_ACCESS_NONE, },
4178 { BASEDIR "\\shared_close", true,
4179 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
4180 { BASEDIR "\\shared_noclose", false,
4181 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
4184 static bool oplock_handler_hold(struct smbcli_transport *transport,
4185 uint16_t tid, uint16_t fnum, uint8_t level,
4188 struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
4189 struct hold_oplock_info *info;
4192 for (i=0;i<ARRAY_SIZE(hold_info);i++) {
4193 if (hold_info[i].fnum == fnum) break;
4196 if (i == ARRAY_SIZE(hold_info)) {
4197 printf("oplock break for unknown fnum %u\n", fnum);
4201 info = &hold_info[i];
4203 if (info->close_on_break) {
4204 printf("oplock break on %s - closing\n",
4206 oplock_handler_close(transport, tid, fnum, level, private_data);
4210 printf("oplock break on %s - acking break\n", info->fname);
4212 return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
4217 used for manual testing of oplocks - especially interaction with
4218 other filesystems (such as NFS and local access)
4220 bool torture_hold_oplock(struct torture_context *torture,
4221 struct smbcli_state *cli)
4223 struct tevent_context *ev = torture->ev;
4226 printf("Setting up open files with oplocks in %s\n", BASEDIR);
4228 torture_assert(torture, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
4230 smbcli_oplock_handler(cli->transport, oplock_handler_hold, cli->tree);
4232 /* setup the files */
4233 for (i=0;i<ARRAY_SIZE(hold_info);i++) {
4238 io.generic.level = RAW_OPEN_NTCREATEX;
4239 io.ntcreatex.in.root_fid.fnum = 0;
4240 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
4241 io.ntcreatex.in.alloc_size = 0;
4242 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
4243 io.ntcreatex.in.share_access = hold_info[i].share_access;
4244 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
4245 io.ntcreatex.in.create_options = 0;
4246 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
4247 io.ntcreatex.in.security_flags = 0;
4248 io.ntcreatex.in.fname = hold_info[i].fname;
4249 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
4250 NTCREATEX_FLAGS_REQUEST_OPLOCK |
4251 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
4252 printf("opening %s\n", hold_info[i].fname);
4254 status = smb_raw_open(cli->tree, cli, &io);
4255 if (!NT_STATUS_IS_OK(status)) {
4256 printf("Failed to open %s - %s\n",
4257 hold_info[i].fname, nt_errstr(status));
4261 if (io.ntcreatex.out.oplock_level != BATCH_OPLOCK_RETURN) {
4262 printf("Oplock not granted for %s - expected %d but got %d\n",
4263 hold_info[i].fname, BATCH_OPLOCK_RETURN,
4264 io.ntcreatex.out.oplock_level);
4267 hold_info[i].fnum = io.ntcreatex.out.file.fnum;
4269 /* make the file non-zero size */
4270 if (smbcli_write(cli->tree, hold_info[i].fnum, 0, &c, 0, 1) != 1) {
4271 printf("Failed to write to file\n");
4276 printf("Waiting for oplock events\n");
4277 tevent_loop_wait(ev);