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