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