s4/torture: Allow receiving of oplock break requests in any order
[Samba/gbeck.git] / source4 / torture / raw / oplock.c
blob6070a0a6ee7a8dc91ca24c41dc0ddd3e4fbc113a
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 "torture/torture.h"
22 #include "torture/smbtorture.h"
23 #include "librpc/gen_ndr/security.h"
24 #include "librpc/gen_ndr/ndr_security.h"
25 #include "libcli/raw/libcliraw.h"
26 #include "libcli/raw/raw_proto.h"
27 #include "libcli/security/security.h"
28 #include "libcli/libcli.h"
29 #include "torture/util.h"
30 #include "lib/events/events.h"
31 #include "param/param.h"
32 #include "lib/cmdline/popt_common.h"
33 #include "libcli/resolve/resolve.h"
35 #define CHECK_VAL(v, correct) do { \
36 if ((v) != (correct)) { \
37 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
38 __location__, #v, (int)v, (int)correct); \
39 ret = false; \
40 }} while (0)
42 #define CHECK_RANGE(v, min, max) do { \
43 if ((v) < (min) || (v) > (max)) { \
44 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got %d - should be between %d and %d\n", \
45 __location__, #v, (int)v, (int)min, (int)max); \
46 ret = false; \
47 }} while (0)
49 #define CHECK_STRMATCH(v, correct) do { \
50 if (!v || strstr((v),(correct)) == NULL) { \
51 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got '%s' - should be '%s'\n", \
52 __location__, #v, v?v:"NULL", correct); \
53 ret = false; \
54 } \
55 } while (0)
57 #define CHECK_STATUS(tctx, status, correct) do { \
58 if (!NT_STATUS_EQUAL(status, correct)) { \
59 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
60 nt_errstr(status), nt_errstr(correct)); \
61 ret = false; \
62 goto done; \
63 }} while (0)
66 static struct {
67 int fnum;
68 uint8_t level;
69 int count;
70 int failures;
71 } break_info;
73 #define BASEDIR "\\test_oplock"
76 a handler function for oplock break requests. Ack it as a break to level II if possible
78 static bool oplock_handler_ack_to_given(struct smbcli_transport *transport,
79 uint16_t tid, uint16_t fnum,
80 uint8_t level, void *private_data)
82 struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
83 const char *name;
85 break_info.fnum = fnum;
86 break_info.level = level;
87 break_info.count++;
89 switch (level) {
90 case OPLOCK_BREAK_TO_LEVEL_II:
91 name = "level II";
92 break;
93 case OPLOCK_BREAK_TO_NONE:
94 name = "none";
95 break;
96 default:
97 name = "unknown";
98 break_info.failures++;
100 printf("Acking to %s [0x%02X] in oplock handler\n",
101 name, level);
103 return smbcli_oplock_ack(tree, fnum, level);
107 a handler function for oplock break requests. Ack it as a break to none
109 static bool oplock_handler_ack_to_none(struct smbcli_transport *transport,
110 uint16_t tid, uint16_t fnum,
111 uint8_t level, void *private_data)
113 struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
114 break_info.fnum = fnum;
115 break_info.level = level;
116 break_info.count++;
118 printf("Acking to none in oplock handler\n");
120 return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
124 a handler function for oplock break requests. Let it timeout
126 static bool oplock_handler_timeout(struct smbcli_transport *transport,
127 uint16_t tid, uint16_t fnum,
128 uint8_t level, void *private_data)
130 break_info.fnum = fnum;
131 break_info.level = level;
132 break_info.count++;
134 printf("Let oplock break timeout\n");
135 return true;
138 static void oplock_handler_close_recv(struct smbcli_request *req)
140 NTSTATUS status;
141 status = smbcli_request_simple_recv(req);
142 if (!NT_STATUS_IS_OK(status)) {
143 printf("close failed in oplock_handler_close\n");
144 break_info.failures++;
149 a handler function for oplock break requests - close the file
151 static bool oplock_handler_close(struct smbcli_transport *transport, uint16_t tid,
152 uint16_t fnum, uint8_t level, void *private_data)
154 union smb_close io;
155 struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
156 struct smbcli_request *req;
158 break_info.fnum = fnum;
159 break_info.level = level;
160 break_info.count++;
162 io.close.level = RAW_CLOSE_CLOSE;
163 io.close.in.file.fnum = fnum;
164 io.close.in.write_time = 0;
165 req = smb_raw_close_send(tree, &io);
166 if (req == NULL) {
167 printf("failed to send close in oplock_handler_close\n");
168 return false;
171 req->async.fn = oplock_handler_close_recv;
172 req->async.private_data = NULL;
174 return true;
177 static bool open_connection_no_level2_oplocks(struct torture_context *tctx,
178 struct smbcli_state **c)
180 NTSTATUS status;
181 struct smbcli_options options;
182 struct smbcli_session_options session_options;
184 lp_smbcli_options(tctx->lp_ctx, &options);
185 lp_smbcli_session_options(tctx->lp_ctx, &session_options);
187 options.use_level2_oplocks = false;
189 status = smbcli_full_connection(tctx, c,
190 torture_setting_string(tctx, "host", NULL),
191 lp_smb_ports(tctx->lp_ctx),
192 torture_setting_string(tctx, "share", NULL),
193 NULL, lp_socket_options(tctx->lp_ctx), cmdline_credentials,
194 lp_resolve_context(tctx->lp_ctx),
195 tctx->ev, &options, &session_options,
196 lp_iconv_convenience(tctx->lp_ctx),
197 lp_gensec_settings(tctx, tctx->lp_ctx));
198 if (!NT_STATUS_IS_OK(status)) {
199 torture_comment(tctx, "Failed to open connection - %s\n",
200 nt_errstr(status));
201 return false;
204 return true;
208 Timer handler function notifies the registering function that time is up
210 static void timeout_cb(struct tevent_context *ev,
211 struct tevent_timer *te,
212 struct timeval current_time,
213 void *private_data)
215 bool *timesup = (bool *)private_data;
216 *timesup = true;
217 return;
221 Wait a short period of time to receive a single oplock break request
223 static void torture_wait_for_oplock_break(struct torture_context *tctx)
225 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
226 struct tevent_timer *te = NULL;
227 struct timeval ne;
228 bool timesup = false;
229 int old_count = break_info.count;
231 /* Wait .1 seconds for an oplock break */
232 ne = tevent_timeval_current_ofs(0, 100000);
234 if ((te = event_add_timed(tctx->ev, tmp_ctx, ne, timeout_cb, &timesup))
235 == NULL)
237 torture_comment(tctx, "Failed to wait for an oplock break. "
238 "test results may not be accurate.");
239 goto done;
242 while (!timesup && break_info.count < old_count + 1) {
243 if (event_loop_once(tctx->ev) != 0) {
244 torture_comment(tctx, "Failed to wait for an oplock "
245 "break. test results may not be "
246 "accurate.");
247 goto done;
251 done:
252 /* We don't know if the timed event fired and was freed, we received
253 * our oplock break, or some other event triggered the loop. Thus,
254 * we create a tmp_ctx to be able to safely free/remove the timed
255 * event in all 3 cases. */
256 talloc_free(tmp_ctx);
258 return;
261 static bool test_raw_oplock_exclusive1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
263 const char *fname = BASEDIR "\\test_exclusive1.dat";
264 NTSTATUS status;
265 bool ret = true;
266 union smb_open io;
267 union smb_unlink unl;
268 uint16_t fnum=0;
270 if (!torture_setup_dir(cli1, BASEDIR)) {
271 return false;
274 /* cleanup */
275 smbcli_unlink(cli1->tree, fname);
277 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
280 base ntcreatex parms
282 io.generic.level = RAW_OPEN_NTCREATEX;
283 io.ntcreatex.in.root_fid = 0;
284 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
285 io.ntcreatex.in.alloc_size = 0;
286 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
287 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
288 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
289 io.ntcreatex.in.create_options = 0;
290 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
291 io.ntcreatex.in.security_flags = 0;
292 io.ntcreatex.in.fname = fname;
294 torture_comment(tctx, "EXCLUSIVE1: open a file with an exclusive oplock (share mode: none)\n");
295 ZERO_STRUCT(break_info);
296 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
298 status = smb_raw_open(cli1->tree, tctx, &io);
299 CHECK_STATUS(tctx, status, NT_STATUS_OK);
300 fnum = io.ntcreatex.out.file.fnum;
301 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
303 torture_comment(tctx, "a 2nd open should not cause a break\n");
304 status = smb_raw_open(cli2->tree, tctx, &io);
305 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
306 torture_wait_for_oplock_break(tctx);
307 CHECK_VAL(break_info.count, 0);
308 CHECK_VAL(break_info.failures, 0);
310 torture_comment(tctx, "unlink it - should also be no break\n");
311 unl.unlink.in.pattern = fname;
312 unl.unlink.in.attrib = 0;
313 status = smb_raw_unlink(cli2->tree, &unl);
314 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
315 torture_wait_for_oplock_break(tctx);
316 CHECK_VAL(break_info.count, 0);
317 CHECK_VAL(break_info.failures, 0);
319 smbcli_close(cli1->tree, fnum);
321 done:
322 smb_raw_exit(cli1->session);
323 smb_raw_exit(cli2->session);
324 smbcli_deltree(cli1->tree, BASEDIR);
325 return ret;
328 static bool test_raw_oplock_exclusive2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
330 const char *fname = BASEDIR "\\test_exclusive2.dat";
331 NTSTATUS status;
332 bool ret = true;
333 union smb_open io;
334 union smb_unlink unl;
335 uint16_t fnum=0, fnum2=0;
337 if (!torture_setup_dir(cli1, BASEDIR)) {
338 return false;
341 /* cleanup */
342 smbcli_unlink(cli1->tree, fname);
344 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
347 base ntcreatex parms
349 io.generic.level = RAW_OPEN_NTCREATEX;
350 io.ntcreatex.in.root_fid = 0;
351 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
352 io.ntcreatex.in.alloc_size = 0;
353 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
354 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
355 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
356 io.ntcreatex.in.create_options = 0;
357 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
358 io.ntcreatex.in.security_flags = 0;
359 io.ntcreatex.in.fname = fname;
361 torture_comment(tctx, "EXCLUSIVE2: open a file with an exclusive oplock (share mode: all)\n");
362 ZERO_STRUCT(break_info);
363 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
364 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
365 NTCREATEX_SHARE_ACCESS_WRITE|
366 NTCREATEX_SHARE_ACCESS_DELETE;
368 status = smb_raw_open(cli1->tree, tctx, &io);
369 CHECK_STATUS(tctx, status, NT_STATUS_OK);
370 fnum = io.ntcreatex.out.file.fnum;
371 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
373 torture_comment(tctx, "a 2nd open should cause a break to level 2\n");
374 status = smb_raw_open(cli2->tree, tctx, &io);
375 CHECK_STATUS(tctx, status, NT_STATUS_OK);
376 fnum2 = io.ntcreatex.out.file.fnum;
377 torture_wait_for_oplock_break(tctx);
378 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
379 CHECK_VAL(break_info.count, 1);
380 CHECK_VAL(break_info.fnum, fnum);
381 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
382 CHECK_VAL(break_info.failures, 0);
383 ZERO_STRUCT(break_info);
385 /* now we have 2 level II oplocks... */
386 torture_comment(tctx, "try to unlink it - should not cause a break, but a sharing violation\n");
387 unl.unlink.in.pattern = fname;
388 unl.unlink.in.attrib = 0;
389 status = smb_raw_unlink(cli2->tree, &unl);
390 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
391 torture_wait_for_oplock_break(tctx);
392 CHECK_VAL(break_info.count, 0);
393 CHECK_VAL(break_info.failures, 0);
395 torture_comment(tctx, "close 1st handle\n");
396 smbcli_close(cli1->tree, fnum);
398 torture_comment(tctx, "try to unlink it - should not cause a break, but a sharing violation\n");
399 unl.unlink.in.pattern = fname;
400 unl.unlink.in.attrib = 0;
401 status = smb_raw_unlink(cli2->tree, &unl);
402 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
403 torture_wait_for_oplock_break(tctx);
404 CHECK_VAL(break_info.count, 0);
405 CHECK_VAL(break_info.failures, 0);
407 torture_comment(tctx, "close 2nd handle\n");
408 smbcli_close(cli2->tree, fnum2);
410 torture_comment(tctx, "unlink it\n");
411 unl.unlink.in.pattern = fname;
412 unl.unlink.in.attrib = 0;
413 status = smb_raw_unlink(cli2->tree, &unl);
414 CHECK_STATUS(tctx, status, NT_STATUS_OK);
415 torture_wait_for_oplock_break(tctx);
416 CHECK_VAL(break_info.count, 0);
417 CHECK_VAL(break_info.failures, 0);
419 done:
420 smb_raw_exit(cli1->session);
421 smb_raw_exit(cli2->session);
422 smbcli_deltree(cli1->tree, BASEDIR);
423 return ret;
426 static bool test_raw_oplock_exclusive3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
428 const char *fname = BASEDIR "\\test_exclusive3.dat";
429 NTSTATUS status;
430 bool ret = true;
431 union smb_open io;
432 union smb_setfileinfo sfi;
433 uint16_t fnum=0;
435 if (!torture_setup_dir(cli1, BASEDIR)) {
436 return false;
439 /* cleanup */
440 smbcli_unlink(cli1->tree, fname);
442 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
445 base ntcreatex parms
447 io.generic.level = RAW_OPEN_NTCREATEX;
448 io.ntcreatex.in.root_fid = 0;
449 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
450 io.ntcreatex.in.alloc_size = 0;
451 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
452 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
453 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
454 io.ntcreatex.in.create_options = 0;
455 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
456 io.ntcreatex.in.security_flags = 0;
457 io.ntcreatex.in.fname = fname;
459 torture_comment(tctx, "EXCLUSIVE3: open a file with an exclusive oplock (share mode: none)\n");
461 ZERO_STRUCT(break_info);
462 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
464 status = smb_raw_open(cli1->tree, tctx, &io);
465 CHECK_STATUS(tctx, status, NT_STATUS_OK);
466 fnum = io.ntcreatex.out.file.fnum;
467 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
469 torture_comment(tctx, "setpathinfo EOF should trigger a break to none\n");
470 ZERO_STRUCT(sfi);
471 sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
472 sfi.generic.in.file.path = fname;
473 sfi.end_of_file_info.in.size = 100;
475 status = smb_raw_setpathinfo(cli2->tree, &sfi);
477 CHECK_STATUS(tctx, status, NT_STATUS_OK);
478 torture_wait_for_oplock_break(tctx);
479 CHECK_VAL(break_info.count, 1);
480 CHECK_VAL(break_info.failures, 0);
481 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
483 smbcli_close(cli1->tree, fnum);
485 done:
486 smb_raw_exit(cli1->session);
487 smb_raw_exit(cli2->session);
488 smbcli_deltree(cli1->tree, BASEDIR);
489 return ret;
492 static bool test_raw_oplock_exclusive4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
494 const char *fname = BASEDIR "\\test_exclusive4.dat";
495 NTSTATUS status;
496 bool ret = true;
497 union smb_open io;
498 uint16_t fnum=0, fnum2=0;
500 if (!torture_setup_dir(cli1, BASEDIR)) {
501 return false;
504 /* cleanup */
505 smbcli_unlink(cli1->tree, fname);
507 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
510 base ntcreatex parms
512 io.generic.level = RAW_OPEN_NTCREATEX;
513 io.ntcreatex.in.root_fid = 0;
514 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
515 io.ntcreatex.in.alloc_size = 0;
516 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
517 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
518 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
519 io.ntcreatex.in.create_options = 0;
520 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
521 io.ntcreatex.in.security_flags = 0;
522 io.ntcreatex.in.fname = fname;
524 torture_comment(tctx, "EXCLUSIVE4: open with exclusive oplock\n");
525 ZERO_STRUCT(break_info);
526 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
528 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
529 status = smb_raw_open(cli1->tree, tctx, &io);
530 CHECK_STATUS(tctx, status, NT_STATUS_OK);
531 fnum = io.ntcreatex.out.file.fnum;
532 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
534 ZERO_STRUCT(break_info);
535 torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
537 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
538 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
539 status = smb_raw_open(cli2->tree, tctx, &io);
540 CHECK_STATUS(tctx, status, NT_STATUS_OK);
541 fnum2 = io.ntcreatex.out.file.fnum;
542 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
543 torture_wait_for_oplock_break(tctx);
544 CHECK_VAL(break_info.count, 0);
545 CHECK_VAL(break_info.failures, 0);
547 smbcli_close(cli1->tree, fnum);
548 smbcli_close(cli2->tree, fnum2);
550 done:
551 smb_raw_exit(cli1->session);
552 smb_raw_exit(cli2->session);
553 smbcli_deltree(cli1->tree, BASEDIR);
554 return ret;
557 static bool test_raw_oplock_exclusive5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
559 const char *fname = BASEDIR "\\test_exclusive5.dat";
560 NTSTATUS status;
561 bool ret = true;
562 union smb_open io;
563 uint16_t fnum=0, fnum2=0;
565 if (!torture_setup_dir(cli1, BASEDIR)) {
566 return false;
569 /* cleanup */
570 smbcli_unlink(cli1->tree, fname);
572 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
573 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
576 base ntcreatex parms
578 io.generic.level = RAW_OPEN_NTCREATEX;
579 io.ntcreatex.in.root_fid = 0;
580 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
581 io.ntcreatex.in.alloc_size = 0;
582 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
583 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
584 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
585 io.ntcreatex.in.create_options = 0;
586 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
587 io.ntcreatex.in.security_flags = 0;
588 io.ntcreatex.in.fname = fname;
590 torture_comment(tctx, "EXCLUSIVE5: open with exclusive oplock\n");
591 ZERO_STRUCT(break_info);
592 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
595 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
596 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
597 NTCREATEX_SHARE_ACCESS_WRITE|
598 NTCREATEX_SHARE_ACCESS_DELETE;
599 status = smb_raw_open(cli1->tree, tctx, &io);
600 CHECK_STATUS(tctx, status, NT_STATUS_OK);
601 fnum = io.ntcreatex.out.file.fnum;
602 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
604 ZERO_STRUCT(break_info);
606 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
608 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
609 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
610 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
611 status = smb_raw_open(cli2->tree, tctx, &io);
612 CHECK_STATUS(tctx, status, NT_STATUS_OK);
613 fnum2 = io.ntcreatex.out.file.fnum;
614 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
615 torture_wait_for_oplock_break(tctx);
616 CHECK_VAL(break_info.count, 1);
617 CHECK_VAL(break_info.failures, 0);
619 smbcli_close(cli1->tree, fnum);
620 smbcli_close(cli2->tree, fnum2);
622 done:
623 smb_raw_exit(cli1->session);
624 smb_raw_exit(cli2->session);
625 smbcli_deltree(cli1->tree, BASEDIR);
626 return ret;
629 static bool test_raw_oplock_exclusive6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
631 const char *fname1 = BASEDIR "\\test_exclusive6_1.dat";
632 const char *fname2 = BASEDIR "\\test_exclusive6_2.dat";
633 NTSTATUS status;
634 bool ret = true;
635 union smb_open io;
636 union smb_rename rn;
637 uint16_t fnum=0;
639 if (!torture_setup_dir(cli1, BASEDIR)) {
640 return false;
643 /* cleanup */
644 smbcli_unlink(cli1->tree, fname1);
645 smbcli_unlink(cli1->tree, fname2);
647 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
650 base ntcreatex parms
652 io.generic.level = RAW_OPEN_NTCREATEX;
653 io.ntcreatex.in.root_fid = 0;
654 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
655 io.ntcreatex.in.alloc_size = 0;
656 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
657 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
658 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
659 io.ntcreatex.in.create_options = 0;
660 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
661 io.ntcreatex.in.security_flags = 0;
662 io.ntcreatex.in.fname = fname1;
664 torture_comment(tctx, "EXCLUSIVE6: open a file with an exclusive "
665 "oplock (share mode: none)\n");
666 ZERO_STRUCT(break_info);
667 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
669 status = smb_raw_open(cli1->tree, tctx, &io);
670 CHECK_STATUS(tctx, status, NT_STATUS_OK);
671 fnum = io.ntcreatex.out.file.fnum;
672 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
674 torture_comment(tctx, "rename should not generate a break but get a "
675 "sharing violation\n");
676 ZERO_STRUCT(rn);
677 rn.generic.level = RAW_RENAME_RENAME;
678 rn.rename.in.pattern1 = fname1;
679 rn.rename.in.pattern2 = fname2;
680 rn.rename.in.attrib = 0;
682 torture_comment(tctx, "trying rename while first file open\n");
683 status = smb_raw_rename(cli2->tree, &rn);
685 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
686 torture_wait_for_oplock_break(tctx);
687 CHECK_VAL(break_info.count, 0);
688 CHECK_VAL(break_info.failures, 0);
690 smbcli_close(cli1->tree, fnum);
692 done:
693 smb_raw_exit(cli1->session);
694 smb_raw_exit(cli2->session);
695 smbcli_deltree(cli1->tree, BASEDIR);
696 return ret;
699 static bool test_raw_oplock_batch1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
701 const char *fname = BASEDIR "\\test_batch1.dat";
702 NTSTATUS status;
703 bool ret = true;
704 union smb_open io;
705 union smb_unlink unl;
706 uint16_t fnum=0;
707 char c = 0;
709 if (!torture_setup_dir(cli1, BASEDIR)) {
710 return false;
713 /* cleanup */
714 smbcli_unlink(cli1->tree, fname);
716 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
719 base ntcreatex parms
721 io.generic.level = RAW_OPEN_NTCREATEX;
722 io.ntcreatex.in.root_fid = 0;
723 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
724 io.ntcreatex.in.alloc_size = 0;
725 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
726 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
727 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
728 io.ntcreatex.in.create_options = 0;
729 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
730 io.ntcreatex.in.security_flags = 0;
731 io.ntcreatex.in.fname = fname;
734 with a batch oplock we get a break
736 torture_comment(tctx, "BATCH1: open with batch oplock\n");
737 ZERO_STRUCT(break_info);
738 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
739 NTCREATEX_FLAGS_REQUEST_OPLOCK |
740 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
741 status = smb_raw_open(cli1->tree, tctx, &io);
742 CHECK_STATUS(tctx, status, NT_STATUS_OK);
743 fnum = io.ntcreatex.out.file.fnum;
744 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
746 torture_comment(tctx, "unlink should generate a break\n");
747 unl.unlink.in.pattern = fname;
748 unl.unlink.in.attrib = 0;
749 status = smb_raw_unlink(cli2->tree, &unl);
750 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
752 torture_wait_for_oplock_break(tctx);
753 CHECK_VAL(break_info.count, 1);
754 CHECK_VAL(break_info.fnum, fnum);
755 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
756 CHECK_VAL(break_info.failures, 0);
758 torture_comment(tctx, "2nd unlink should not generate a break\n");
759 ZERO_STRUCT(break_info);
760 status = smb_raw_unlink(cli2->tree, &unl);
761 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
763 torture_wait_for_oplock_break(tctx);
764 CHECK_VAL(break_info.count, 0);
766 torture_comment(tctx, "writing should generate a self break to none\n");
767 smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
769 torture_wait_for_oplock_break(tctx);
770 torture_wait_for_oplock_break(tctx);
771 CHECK_VAL(break_info.count, 1);
772 CHECK_VAL(break_info.fnum, fnum);
773 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
774 CHECK_VAL(break_info.failures, 0);
776 smbcli_close(cli1->tree, fnum);
778 done:
779 smb_raw_exit(cli1->session);
780 smb_raw_exit(cli2->session);
781 smbcli_deltree(cli1->tree, BASEDIR);
782 return ret;
785 static bool test_raw_oplock_batch2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
787 const char *fname = BASEDIR "\\test_batch2.dat";
788 NTSTATUS status;
789 bool ret = true;
790 union smb_open io;
791 union smb_unlink unl;
792 uint16_t fnum=0;
793 char c = 0;
795 if (!torture_setup_dir(cli1, BASEDIR)) {
796 return false;
799 /* cleanup */
800 smbcli_unlink(cli1->tree, fname);
802 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
805 base ntcreatex parms
807 io.generic.level = RAW_OPEN_NTCREATEX;
808 io.ntcreatex.in.root_fid = 0;
809 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
810 io.ntcreatex.in.alloc_size = 0;
811 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
812 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
813 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
814 io.ntcreatex.in.create_options = 0;
815 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
816 io.ntcreatex.in.security_flags = 0;
817 io.ntcreatex.in.fname = fname;
819 torture_comment(tctx, "BATCH2: open with batch oplock\n");
820 ZERO_STRUCT(break_info);
821 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
822 NTCREATEX_FLAGS_REQUEST_OPLOCK |
823 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
824 status = smb_raw_open(cli1->tree, tctx, &io);
825 CHECK_STATUS(tctx, status, NT_STATUS_OK);
826 fnum = io.ntcreatex.out.file.fnum;
827 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
829 torture_comment(tctx, "unlink should generate a break, which we ack as break to none\n");
830 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_none, cli1->tree);
831 unl.unlink.in.pattern = fname;
832 unl.unlink.in.attrib = 0;
833 status = smb_raw_unlink(cli2->tree, &unl);
834 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
836 torture_wait_for_oplock_break(tctx);
837 CHECK_VAL(break_info.count, 1);
838 CHECK_VAL(break_info.fnum, fnum);
839 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
840 CHECK_VAL(break_info.failures, 0);
842 torture_comment(tctx, "2nd unlink should not generate a break\n");
843 ZERO_STRUCT(break_info);
844 status = smb_raw_unlink(cli2->tree, &unl);
845 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
847 torture_wait_for_oplock_break(tctx);
848 CHECK_VAL(break_info.count, 0);
850 torture_comment(tctx, "writing should not generate a break\n");
851 smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
853 torture_wait_for_oplock_break(tctx);
854 CHECK_VAL(break_info.count, 0);
856 smbcli_close(cli1->tree, fnum);
858 done:
859 smb_raw_exit(cli1->session);
860 smb_raw_exit(cli2->session);
861 smbcli_deltree(cli1->tree, BASEDIR);
862 return ret;
865 static bool test_raw_oplock_batch3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
867 const char *fname = BASEDIR "\\test_batch3.dat";
868 NTSTATUS status;
869 bool ret = true;
870 union smb_open io;
871 union smb_unlink unl;
872 uint16_t fnum=0;
874 if (!torture_setup_dir(cli1, BASEDIR)) {
875 return false;
878 /* cleanup */
879 smbcli_unlink(cli1->tree, fname);
881 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
884 base ntcreatex parms
886 io.generic.level = RAW_OPEN_NTCREATEX;
887 io.ntcreatex.in.root_fid = 0;
888 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
889 io.ntcreatex.in.alloc_size = 0;
890 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
891 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
892 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
893 io.ntcreatex.in.create_options = 0;
894 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
895 io.ntcreatex.in.security_flags = 0;
896 io.ntcreatex.in.fname = fname;
898 torture_comment(tctx, "BATCH3: if we close on break then the unlink can succeed\n");
899 ZERO_STRUCT(break_info);
900 smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
901 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
902 NTCREATEX_FLAGS_REQUEST_OPLOCK |
903 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
904 status = smb_raw_open(cli1->tree, tctx, &io);
905 CHECK_STATUS(tctx, status, NT_STATUS_OK);
906 fnum = io.ntcreatex.out.file.fnum;
907 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
909 unl.unlink.in.pattern = fname;
910 unl.unlink.in.attrib = 0;
911 ZERO_STRUCT(break_info);
912 status = smb_raw_unlink(cli2->tree, &unl);
913 CHECK_STATUS(tctx, status, NT_STATUS_OK);
915 torture_wait_for_oplock_break(tctx);
916 CHECK_VAL(break_info.count, 1);
917 CHECK_VAL(break_info.fnum, fnum);
918 CHECK_VAL(break_info.level, 1);
919 CHECK_VAL(break_info.failures, 0);
921 smbcli_close(cli1->tree, fnum);
923 done:
924 smb_raw_exit(cli1->session);
925 smb_raw_exit(cli2->session);
926 smbcli_deltree(cli1->tree, BASEDIR);
927 return ret;
930 static bool test_raw_oplock_batch4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
932 const char *fname = BASEDIR "\\test_batch4.dat";
933 NTSTATUS status;
934 bool ret = true;
935 union smb_open io;
936 union smb_read rd;
937 uint16_t fnum=0;
939 if (!torture_setup_dir(cli1, BASEDIR)) {
940 return false;
943 /* cleanup */
944 smbcli_unlink(cli1->tree, fname);
946 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
949 base ntcreatex parms
951 io.generic.level = RAW_OPEN_NTCREATEX;
952 io.ntcreatex.in.root_fid = 0;
953 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
954 io.ntcreatex.in.alloc_size = 0;
955 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
956 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
957 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
958 io.ntcreatex.in.create_options = 0;
959 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
960 io.ntcreatex.in.security_flags = 0;
961 io.ntcreatex.in.fname = fname;
963 torture_comment(tctx, "BATCH4: a self read should not cause a break\n");
964 ZERO_STRUCT(break_info);
965 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
967 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
968 NTCREATEX_FLAGS_REQUEST_OPLOCK |
969 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
970 status = smb_raw_open(cli1->tree, tctx, &io);
971 CHECK_STATUS(tctx, status, NT_STATUS_OK);
972 fnum = io.ntcreatex.out.file.fnum;
973 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
975 rd.read.level = RAW_READ_READ;
976 rd.read.in.file.fnum = fnum;
977 rd.read.in.count = 1;
978 rd.read.in.offset = 0;
979 rd.read.in.remaining = 0;
980 status = smb_raw_read(cli1->tree, &rd);
981 CHECK_STATUS(tctx, status, NT_STATUS_OK);
982 torture_wait_for_oplock_break(tctx);
983 CHECK_VAL(break_info.count, 0);
984 CHECK_VAL(break_info.failures, 0);
986 smbcli_close(cli1->tree, fnum);
988 done:
989 smb_raw_exit(cli1->session);
990 smb_raw_exit(cli2->session);
991 smbcli_deltree(cli1->tree, BASEDIR);
992 return ret;
995 static bool test_raw_oplock_batch5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
997 const char *fname = BASEDIR "\\test_batch5.dat";
998 NTSTATUS status;
999 bool ret = true;
1000 union smb_open io;
1001 uint16_t fnum=0;
1003 if (!torture_setup_dir(cli1, BASEDIR)) {
1004 return false;
1007 /* cleanup */
1008 smbcli_unlink(cli1->tree, fname);
1010 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1013 base ntcreatex parms
1015 io.generic.level = RAW_OPEN_NTCREATEX;
1016 io.ntcreatex.in.root_fid = 0;
1017 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1018 io.ntcreatex.in.alloc_size = 0;
1019 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1020 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1021 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1022 io.ntcreatex.in.create_options = 0;
1023 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1024 io.ntcreatex.in.security_flags = 0;
1025 io.ntcreatex.in.fname = fname;
1027 torture_comment(tctx, "BATCH5: a 2nd open should give a break\n");
1028 ZERO_STRUCT(break_info);
1029 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1031 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1032 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1033 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1034 status = smb_raw_open(cli1->tree, tctx, &io);
1035 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1036 fnum = io.ntcreatex.out.file.fnum;
1037 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1039 ZERO_STRUCT(break_info);
1041 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1042 status = smb_raw_open(cli2->tree, tctx, &io);
1043 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1045 torture_wait_for_oplock_break(tctx);
1046 CHECK_VAL(break_info.count, 1);
1047 CHECK_VAL(break_info.fnum, fnum);
1048 CHECK_VAL(break_info.level, 1);
1049 CHECK_VAL(break_info.failures, 0);
1051 smbcli_close(cli1->tree, fnum);
1053 done:
1054 smb_raw_exit(cli1->session);
1055 smb_raw_exit(cli2->session);
1056 smbcli_deltree(cli1->tree, BASEDIR);
1057 return ret;
1060 static bool test_raw_oplock_batch6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1062 const char *fname = BASEDIR "\\test_batch6.dat";
1063 NTSTATUS status;
1064 bool ret = true;
1065 union smb_open io;
1066 uint16_t fnum=0, fnum2=0;
1067 char c = 0;
1069 if (!torture_setup_dir(cli1, BASEDIR)) {
1070 return false;
1073 /* cleanup */
1074 smbcli_unlink(cli1->tree, fname);
1076 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1077 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1080 base ntcreatex parms
1082 io.generic.level = RAW_OPEN_NTCREATEX;
1083 io.ntcreatex.in.root_fid = 0;
1084 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1085 io.ntcreatex.in.alloc_size = 0;
1086 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1087 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1088 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1089 io.ntcreatex.in.create_options = 0;
1090 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1091 io.ntcreatex.in.security_flags = 0;
1092 io.ntcreatex.in.fname = fname;
1094 torture_comment(tctx, "BATCH6: a 2nd open should give a break to level II if the first open allowed shared read\n");
1095 ZERO_STRUCT(break_info);
1097 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
1098 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
1099 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1100 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1101 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1102 status = smb_raw_open(cli1->tree, tctx, &io);
1103 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1104 fnum = io.ntcreatex.out.file.fnum;
1105 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1107 ZERO_STRUCT(break_info);
1109 status = smb_raw_open(cli2->tree, tctx, &io);
1110 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1111 fnum2 = io.ntcreatex.out.file.fnum;
1112 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1114 //torture_wait_for_oplock_break(tctx);
1115 CHECK_VAL(break_info.count, 1);
1116 CHECK_VAL(break_info.fnum, fnum);
1117 CHECK_VAL(break_info.level, 1);
1118 CHECK_VAL(break_info.failures, 0);
1119 ZERO_STRUCT(break_info);
1121 torture_comment(tctx, "write should trigger a break to none on both\n");
1122 smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
1124 /* We expect two breaks */
1125 torture_wait_for_oplock_break(tctx);
1126 torture_wait_for_oplock_break(tctx);
1128 CHECK_VAL(break_info.count, 2);
1129 CHECK_VAL(break_info.level, 0);
1130 CHECK_VAL(break_info.failures, 0);
1132 smbcli_close(cli1->tree, fnum);
1133 smbcli_close(cli2->tree, fnum2);
1135 done:
1136 smb_raw_exit(cli1->session);
1137 smb_raw_exit(cli2->session);
1138 smbcli_deltree(cli1->tree, BASEDIR);
1139 return ret;
1142 static bool test_raw_oplock_batch7(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1144 const char *fname = BASEDIR "\\test_batch7.dat";
1145 NTSTATUS status;
1146 bool ret = true;
1147 union smb_open io;
1148 uint16_t fnum=0, fnum2=0;
1150 if (!torture_setup_dir(cli1, BASEDIR)) {
1151 return false;
1154 /* cleanup */
1155 smbcli_unlink(cli1->tree, fname);
1157 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1160 base ntcreatex parms
1162 io.generic.level = RAW_OPEN_NTCREATEX;
1163 io.ntcreatex.in.root_fid = 0;
1164 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1165 io.ntcreatex.in.alloc_size = 0;
1166 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1167 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1168 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1169 io.ntcreatex.in.create_options = 0;
1170 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1171 io.ntcreatex.in.security_flags = 0;
1172 io.ntcreatex.in.fname = fname;
1174 torture_comment(tctx, "BATCH7: a 2nd open should get an oplock when we close instead of ack\n");
1175 ZERO_STRUCT(break_info);
1176 smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
1178 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1179 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1180 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1181 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1182 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1183 status = smb_raw_open(cli1->tree, tctx, &io);
1184 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1185 fnum2 = io.ntcreatex.out.file.fnum;
1186 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1188 ZERO_STRUCT(break_info);
1190 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1191 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1192 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1193 status = smb_raw_open(cli2->tree, tctx, &io);
1194 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1195 fnum = io.ntcreatex.out.file.fnum;
1196 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1198 torture_wait_for_oplock_break(tctx);
1199 CHECK_VAL(break_info.count, 1);
1200 CHECK_VAL(break_info.fnum, fnum2);
1201 CHECK_VAL(break_info.level, 1);
1202 CHECK_VAL(break_info.failures, 0);
1204 smbcli_close(cli2->tree, fnum);
1206 done:
1207 smb_raw_exit(cli1->session);
1208 smb_raw_exit(cli2->session);
1209 smbcli_deltree(cli1->tree, BASEDIR);
1210 return ret;
1213 static bool test_raw_oplock_batch8(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1215 const char *fname = BASEDIR "\\test_batch8.dat";
1216 NTSTATUS status;
1217 bool ret = true;
1218 union smb_open io;
1219 uint16_t fnum=0, fnum2=0;
1221 if (!torture_setup_dir(cli1, BASEDIR)) {
1222 return false;
1225 /* cleanup */
1226 smbcli_unlink(cli1->tree, fname);
1228 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1231 base ntcreatex parms
1233 io.generic.level = RAW_OPEN_NTCREATEX;
1234 io.ntcreatex.in.root_fid = 0;
1235 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1236 io.ntcreatex.in.alloc_size = 0;
1237 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1238 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1239 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1240 io.ntcreatex.in.create_options = 0;
1241 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1242 io.ntcreatex.in.security_flags = 0;
1243 io.ntcreatex.in.fname = fname;
1245 torture_comment(tctx, "BATCH8: open with batch oplock\n");
1246 ZERO_STRUCT(break_info);
1247 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1249 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1250 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1251 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1252 status = smb_raw_open(cli1->tree, tctx, &io);
1253 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1254 fnum = io.ntcreatex.out.file.fnum;
1255 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1257 ZERO_STRUCT(break_info);
1258 torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
1260 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1261 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1262 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1263 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1264 status = smb_raw_open(cli2->tree, tctx, &io);
1265 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1266 fnum2 = io.ntcreatex.out.file.fnum;
1267 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
1268 torture_wait_for_oplock_break(tctx);
1269 CHECK_VAL(break_info.count, 0);
1270 CHECK_VAL(break_info.failures, 0);
1272 smbcli_close(cli1->tree, fnum);
1273 smbcli_close(cli2->tree, fnum2);
1275 done:
1276 smb_raw_exit(cli1->session);
1277 smb_raw_exit(cli2->session);
1278 smbcli_deltree(cli1->tree, BASEDIR);
1279 return ret;
1282 static bool test_raw_oplock_batch9(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1284 const char *fname = BASEDIR "\\test_batch9.dat";
1285 NTSTATUS status;
1286 bool ret = true;
1287 union smb_open io;
1288 uint16_t fnum=0, fnum2=0;
1289 char c = 0;
1291 if (!torture_setup_dir(cli1, BASEDIR)) {
1292 return false;
1295 /* cleanup */
1296 smbcli_unlink(cli1->tree, fname);
1298 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1301 base ntcreatex parms
1303 io.generic.level = RAW_OPEN_NTCREATEX;
1304 io.ntcreatex.in.root_fid = 0;
1305 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1306 io.ntcreatex.in.alloc_size = 0;
1307 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1308 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1309 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1310 io.ntcreatex.in.create_options = 0;
1311 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1312 io.ntcreatex.in.security_flags = 0;
1313 io.ntcreatex.in.fname = fname;
1315 torture_comment(tctx, "BATCH9: open with attributes only can create file\n");
1317 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1318 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1319 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1320 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1321 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1322 status = smb_raw_open(cli1->tree, tctx, &io);
1323 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1324 fnum = io.ntcreatex.out.file.fnum;
1325 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1327 torture_comment(tctx, "Subsequent normal open should break oplock on attribute only open to level II\n");
1329 ZERO_STRUCT(break_info);
1330 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1332 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1333 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1334 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1335 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1336 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1337 status = smb_raw_open(cli2->tree, tctx, &io);
1338 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1339 fnum2 = io.ntcreatex.out.file.fnum;
1340 torture_wait_for_oplock_break(tctx);
1341 CHECK_VAL(break_info.count, 1);
1342 CHECK_VAL(break_info.fnum, fnum);
1343 CHECK_VAL(break_info.failures, 0);
1344 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1345 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1346 smbcli_close(cli2->tree, fnum2);
1348 torture_comment(tctx, "third oplocked open should grant level2 without break\n");
1349 ZERO_STRUCT(break_info);
1350 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1351 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1352 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1353 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1354 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1355 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1356 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1357 status = smb_raw_open(cli2->tree, tctx, &io);
1358 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1359 fnum2 = io.ntcreatex.out.file.fnum;
1360 torture_wait_for_oplock_break(tctx);
1361 CHECK_VAL(break_info.count, 0);
1362 CHECK_VAL(break_info.failures, 0);
1363 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1365 ZERO_STRUCT(break_info);
1367 torture_comment(tctx, "write should trigger a break to none on both\n");
1368 smbcli_write(cli2->tree, fnum2, 0, &c, 0, 1);
1370 /* We expect two breaks */
1371 torture_wait_for_oplock_break(tctx);
1372 torture_wait_for_oplock_break(tctx);
1374 CHECK_VAL(break_info.count, 2);
1375 CHECK_VAL(break_info.level, 0);
1376 CHECK_VAL(break_info.failures, 0);
1378 smbcli_close(cli1->tree, fnum);
1379 smbcli_close(cli2->tree, fnum2);
1381 done:
1382 smb_raw_exit(cli1->session);
1383 smb_raw_exit(cli2->session);
1384 smbcli_deltree(cli1->tree, BASEDIR);
1385 return ret;
1388 static bool test_raw_oplock_batch10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1390 const char *fname = BASEDIR "\\test_batch10.dat";
1391 NTSTATUS status;
1392 bool ret = true;
1393 union smb_open io;
1394 uint16_t fnum=0, fnum2=0;
1396 if (!torture_setup_dir(cli1, BASEDIR)) {
1397 return false;
1400 /* cleanup */
1401 smbcli_unlink(cli1->tree, fname);
1403 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1406 base ntcreatex parms
1408 io.generic.level = RAW_OPEN_NTCREATEX;
1409 io.ntcreatex.in.root_fid = 0;
1410 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1411 io.ntcreatex.in.alloc_size = 0;
1412 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1413 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1414 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1415 io.ntcreatex.in.create_options = 0;
1416 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1417 io.ntcreatex.in.security_flags = 0;
1418 io.ntcreatex.in.fname = fname;
1420 torture_comment(tctx, "BATCH10: Open with oplock after a non-oplock open should grant level2\n");
1421 ZERO_STRUCT(break_info);
1422 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1423 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1424 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1425 NTCREATEX_SHARE_ACCESS_WRITE|
1426 NTCREATEX_SHARE_ACCESS_DELETE;
1427 status = smb_raw_open(cli1->tree, tctx, &io);
1428 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1429 fnum = io.ntcreatex.out.file.fnum;
1430 torture_wait_for_oplock_break(tctx);
1431 CHECK_VAL(break_info.count, 0);
1432 CHECK_VAL(break_info.failures, 0);
1433 CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
1435 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1437 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1438 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1439 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1440 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1441 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1442 NTCREATEX_SHARE_ACCESS_WRITE|
1443 NTCREATEX_SHARE_ACCESS_DELETE;
1444 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1445 status = smb_raw_open(cli2->tree, tctx, &io);
1446 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1447 fnum2 = io.ntcreatex.out.file.fnum;
1448 torture_wait_for_oplock_break(tctx);
1449 CHECK_VAL(break_info.count, 0);
1450 CHECK_VAL(break_info.failures, 0);
1451 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1453 torture_comment(tctx, "write should trigger a break to none\n");
1455 union smb_write wr;
1456 wr.write.level = RAW_WRITE_WRITE;
1457 wr.write.in.file.fnum = fnum;
1458 wr.write.in.count = 1;
1459 wr.write.in.offset = 0;
1460 wr.write.in.remaining = 0;
1461 wr.write.in.data = (const uint8_t *)"x";
1462 status = smb_raw_write(cli1->tree, &wr);
1463 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1466 torture_wait_for_oplock_break(tctx);
1468 CHECK_VAL(break_info.count, 1);
1469 CHECK_VAL(break_info.fnum, fnum2);
1470 CHECK_VAL(break_info.level, 0);
1471 CHECK_VAL(break_info.failures, 0);
1473 smbcli_close(cli1->tree, fnum);
1474 smbcli_close(cli2->tree, fnum2);
1476 done:
1477 smb_raw_exit(cli1->session);
1478 smb_raw_exit(cli2->session);
1479 smbcli_deltree(cli1->tree, BASEDIR);
1480 return ret;
1483 static bool test_raw_oplock_batch11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1485 const char *fname = BASEDIR "\\test_batch11.dat";
1486 NTSTATUS status;
1487 bool ret = true;
1488 union smb_open io;
1489 union smb_setfileinfo sfi;
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 = 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 /* Test if a set-eof on pathname breaks an exclusive oplock. */
1517 torture_comment(tctx, "BATCH11: Test if setpathinfo set EOF breaks oplocks.\n");
1519 ZERO_STRUCT(break_info);
1521 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1522 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1523 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1524 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1525 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1526 NTCREATEX_SHARE_ACCESS_WRITE|
1527 NTCREATEX_SHARE_ACCESS_DELETE;
1528 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1529 status = smb_raw_open(cli1->tree, tctx, &io);
1530 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1531 fnum = io.ntcreatex.out.file.fnum;
1532 torture_wait_for_oplock_break(tctx);
1533 CHECK_VAL(break_info.count, 0);
1534 CHECK_VAL(break_info.failures, 0);
1535 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1537 ZERO_STRUCT(sfi);
1538 sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1539 sfi.generic.in.file.path = fname;
1540 sfi.end_of_file_info.in.size = 100;
1542 status = smb_raw_setpathinfo(cli2->tree, &sfi);
1543 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1545 torture_wait_for_oplock_break(tctx);
1546 CHECK_VAL(break_info.count, 1);
1547 CHECK_VAL(break_info.failures, 0);
1548 CHECK_VAL(break_info.level, 0);
1550 smbcli_close(cli1->tree, fnum);
1552 done:
1553 smb_raw_exit(cli1->session);
1554 smb_raw_exit(cli2->session);
1555 smbcli_deltree(cli1->tree, BASEDIR);
1556 return ret;
1559 static bool test_raw_oplock_batch12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1561 const char *fname = BASEDIR "\\test_batch12.dat";
1562 NTSTATUS status;
1563 bool ret = true;
1564 union smb_open io;
1565 union smb_setfileinfo sfi;
1566 uint16_t fnum=0;
1568 if (!torture_setup_dir(cli1, BASEDIR)) {
1569 return false;
1572 /* cleanup */
1573 smbcli_unlink(cli1->tree, fname);
1575 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1578 base ntcreatex parms
1580 io.generic.level = RAW_OPEN_NTCREATEX;
1581 io.ntcreatex.in.root_fid = 0;
1582 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1583 io.ntcreatex.in.alloc_size = 0;
1584 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1585 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1586 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1587 io.ntcreatex.in.create_options = 0;
1588 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1589 io.ntcreatex.in.security_flags = 0;
1590 io.ntcreatex.in.fname = fname;
1592 /* Test if a set-allocation size on pathname breaks an exclusive oplock. */
1593 torture_comment(tctx, "BATCH12: Test if setpathinfo allocation size breaks oplocks.\n");
1595 ZERO_STRUCT(break_info);
1596 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1598 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1599 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1600 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1601 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1602 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1603 NTCREATEX_SHARE_ACCESS_WRITE|
1604 NTCREATEX_SHARE_ACCESS_DELETE;
1605 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1606 status = smb_raw_open(cli1->tree, tctx, &io);
1607 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1608 fnum = io.ntcreatex.out.file.fnum;
1609 torture_wait_for_oplock_break(tctx);
1610 CHECK_VAL(break_info.count, 0);
1611 CHECK_VAL(break_info.failures, 0);
1612 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1614 ZERO_STRUCT(sfi);
1615 sfi.generic.level = SMB_SFILEINFO_ALLOCATION_INFORMATION;
1616 sfi.generic.in.file.path = fname;
1617 sfi.allocation_info.in.alloc_size = 65536 * 8;
1619 status = smb_raw_setpathinfo(cli2->tree, &sfi);
1620 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1622 torture_wait_for_oplock_break(tctx);
1623 CHECK_VAL(break_info.count, 1);
1624 CHECK_VAL(break_info.failures, 0);
1625 CHECK_VAL(break_info.level, 0);
1627 smbcli_close(cli1->tree, fnum);
1629 done:
1630 smb_raw_exit(cli1->session);
1631 smb_raw_exit(cli2->session);
1632 smbcli_deltree(cli1->tree, BASEDIR);
1633 return ret;
1636 static bool test_raw_oplock_batch13(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1638 const char *fname = BASEDIR "\\test_batch13.dat";
1639 NTSTATUS status;
1640 bool ret = true;
1641 union smb_open io;
1642 uint16_t fnum=0, fnum2=0;
1644 if (!torture_setup_dir(cli1, BASEDIR)) {
1645 return false;
1648 /* cleanup */
1649 smbcli_unlink(cli1->tree, fname);
1651 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1652 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
1655 base ntcreatex parms
1657 io.generic.level = RAW_OPEN_NTCREATEX;
1658 io.ntcreatex.in.root_fid = 0;
1659 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1660 io.ntcreatex.in.alloc_size = 0;
1661 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1662 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1663 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1664 io.ntcreatex.in.create_options = 0;
1665 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1666 io.ntcreatex.in.security_flags = 0;
1667 io.ntcreatex.in.fname = fname;
1669 torture_comment(tctx, "BATCH13: open with batch oplock\n");
1670 ZERO_STRUCT(break_info);
1672 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1673 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1674 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1675 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1676 NTCREATEX_SHARE_ACCESS_WRITE|
1677 NTCREATEX_SHARE_ACCESS_DELETE;
1678 status = smb_raw_open(cli1->tree, tctx, &io);
1679 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1680 fnum = io.ntcreatex.out.file.fnum;
1681 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1683 ZERO_STRUCT(break_info);
1685 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE dispostion causes oplock break\n");
1687 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1688 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1689 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1690 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1691 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1692 NTCREATEX_SHARE_ACCESS_WRITE|
1693 NTCREATEX_SHARE_ACCESS_DELETE;
1694 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
1695 status = smb_raw_open(cli2->tree, tctx, &io);
1696 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1697 fnum2 = io.ntcreatex.out.file.fnum;
1698 torture_wait_for_oplock_break(tctx);
1699 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1700 CHECK_VAL(break_info.count, 1);
1701 CHECK_VAL(break_info.failures, 0);
1703 smbcli_close(cli1->tree, fnum);
1704 smbcli_close(cli2->tree, fnum2);
1706 done:
1707 smb_raw_exit(cli1->session);
1708 smb_raw_exit(cli2->session);
1709 smbcli_deltree(cli1->tree, BASEDIR);
1710 return ret;
1713 static bool test_raw_oplock_batch14(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1715 const char *fname = BASEDIR "\\test_batch14.dat";
1716 NTSTATUS status;
1717 bool ret = true;
1718 union smb_open io;
1719 uint16_t fnum=0, fnum2=0;
1721 if (!torture_setup_dir(cli1, BASEDIR)) {
1722 return false;
1725 /* cleanup */
1726 smbcli_unlink(cli1->tree, fname);
1728 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1731 base ntcreatex parms
1733 io.generic.level = RAW_OPEN_NTCREATEX;
1734 io.ntcreatex.in.root_fid = 0;
1735 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1736 io.ntcreatex.in.alloc_size = 0;
1737 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1738 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1739 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1740 io.ntcreatex.in.create_options = 0;
1741 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1742 io.ntcreatex.in.security_flags = 0;
1743 io.ntcreatex.in.fname = fname;
1745 torture_comment(tctx, "BATCH14: open with batch oplock\n");
1746 ZERO_STRUCT(break_info);
1748 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1749 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1750 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1751 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1752 NTCREATEX_SHARE_ACCESS_WRITE|
1753 NTCREATEX_SHARE_ACCESS_DELETE;
1754 status = smb_raw_open(cli1->tree, tctx, &io);
1755 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1756 fnum = io.ntcreatex.out.file.fnum;
1757 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1759 ZERO_STRUCT(break_info);
1761 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_SUPERSEDE dispostion causes oplock break\n");
1763 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1764 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1765 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1766 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1767 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1768 NTCREATEX_SHARE_ACCESS_WRITE|
1769 NTCREATEX_SHARE_ACCESS_DELETE;
1770 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
1771 status = smb_raw_open(cli2->tree, tctx, &io);
1772 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1773 fnum2 = io.ntcreatex.out.file.fnum;
1774 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1776 torture_wait_for_oplock_break(tctx);
1777 CHECK_VAL(break_info.count, 1);
1778 CHECK_VAL(break_info.failures, 0);
1780 smbcli_close(cli1->tree, fnum);
1781 smbcli_close(cli2->tree, fnum2);
1782 done:
1783 smb_raw_exit(cli1->session);
1784 smb_raw_exit(cli2->session);
1785 smbcli_deltree(cli1->tree, BASEDIR);
1786 return ret;
1789 static bool test_raw_oplock_batch15(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1791 const char *fname = BASEDIR "\\test_batch15.dat";
1792 NTSTATUS status;
1793 bool ret = true;
1794 union smb_open io;
1795 union smb_fileinfo qfi;
1796 uint16_t fnum=0;
1798 if (!torture_setup_dir(cli1, BASEDIR)) {
1799 return false;
1802 /* cleanup */
1803 smbcli_unlink(cli1->tree, fname);
1805 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1808 base ntcreatex parms
1810 io.generic.level = RAW_OPEN_NTCREATEX;
1811 io.ntcreatex.in.root_fid = 0;
1812 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1813 io.ntcreatex.in.alloc_size = 0;
1814 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1815 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1816 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1817 io.ntcreatex.in.create_options = 0;
1818 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1819 io.ntcreatex.in.security_flags = 0;
1820 io.ntcreatex.in.fname = fname;
1822 /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
1823 torture_comment(tctx, "BATCH15: Test if qpathinfo all info breaks a batch oplock (should not).\n");
1825 ZERO_STRUCT(break_info);
1827 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1828 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1829 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1830 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1831 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1832 NTCREATEX_SHARE_ACCESS_WRITE|
1833 NTCREATEX_SHARE_ACCESS_DELETE;
1834 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1835 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1836 status = smb_raw_open(cli1->tree, tctx, &io);
1837 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1838 fnum = io.ntcreatex.out.file.fnum;
1840 torture_wait_for_oplock_break(tctx);
1841 CHECK_VAL(break_info.count, 0);
1842 CHECK_VAL(break_info.failures, 0);
1843 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1845 ZERO_STRUCT(qfi);
1846 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1847 qfi.generic.in.file.path = fname;
1849 status = smb_raw_pathinfo(cli2->tree, tctx, &qfi);
1850 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1852 torture_wait_for_oplock_break(tctx);
1853 CHECK_VAL(break_info.count, 0);
1855 smbcli_close(cli1->tree, fnum);
1857 done:
1858 smb_raw_exit(cli1->session);
1859 smb_raw_exit(cli2->session);
1860 smbcli_deltree(cli1->tree, BASEDIR);
1861 return ret;
1864 static bool test_raw_oplock_batch16(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1866 const char *fname = BASEDIR "\\test_batch16.dat";
1867 NTSTATUS status;
1868 bool ret = true;
1869 union smb_open io;
1870 uint16_t fnum=0, fnum2=0;
1872 if (!torture_setup_dir(cli1, BASEDIR)) {
1873 return false;
1876 /* cleanup */
1877 smbcli_unlink(cli1->tree, fname);
1879 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1880 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
1883 base ntcreatex parms
1885 io.generic.level = RAW_OPEN_NTCREATEX;
1886 io.ntcreatex.in.root_fid = 0;
1887 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1888 io.ntcreatex.in.alloc_size = 0;
1889 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1890 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1891 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1892 io.ntcreatex.in.create_options = 0;
1893 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1894 io.ntcreatex.in.security_flags = 0;
1895 io.ntcreatex.in.fname = fname;
1897 torture_comment(tctx, "BATCH16: open with batch oplock\n");
1898 ZERO_STRUCT(break_info);
1900 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1901 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1902 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1903 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1904 NTCREATEX_SHARE_ACCESS_WRITE|
1905 NTCREATEX_SHARE_ACCESS_DELETE;
1906 status = smb_raw_open(cli1->tree, tctx, &io);
1907 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1908 fnum = io.ntcreatex.out.file.fnum;
1909 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1911 ZERO_STRUCT(break_info);
1913 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
1915 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1916 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1917 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1918 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1919 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1920 NTCREATEX_SHARE_ACCESS_WRITE|
1921 NTCREATEX_SHARE_ACCESS_DELETE;
1922 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1923 status = smb_raw_open(cli2->tree, tctx, &io);
1924 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1925 fnum2 = io.ntcreatex.out.file.fnum;
1926 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1928 torture_wait_for_oplock_break(tctx);
1929 CHECK_VAL(break_info.count, 1);
1930 CHECK_VAL(break_info.failures, 0);
1932 smbcli_close(cli1->tree, fnum);
1933 smbcli_close(cli2->tree, fnum2);
1935 done:
1936 smb_raw_exit(cli1->session);
1937 smb_raw_exit(cli2->session);
1938 smbcli_deltree(cli1->tree, BASEDIR);
1939 return ret;
1942 static bool test_raw_oplock_batch17(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1944 const char *fname1 = BASEDIR "\\test_batch17_1.dat";
1945 const char *fname2 = BASEDIR "\\test_batch17_2.dat";
1946 NTSTATUS status;
1947 bool ret = true;
1948 union smb_open io;
1949 union smb_rename rn;
1950 uint16_t fnum=0;
1952 if (!torture_setup_dir(cli1, BASEDIR)) {
1953 return false;
1956 /* cleanup */
1957 smbcli_unlink(cli1->tree, fname1);
1958 smbcli_unlink(cli1->tree, fname2);
1960 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1963 base ntcreatex parms
1965 io.generic.level = RAW_OPEN_NTCREATEX;
1966 io.ntcreatex.in.root_fid = 0;
1967 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1968 io.ntcreatex.in.alloc_size = 0;
1969 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1970 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1971 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1972 io.ntcreatex.in.create_options = 0;
1973 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1974 io.ntcreatex.in.security_flags = 0;
1975 io.ntcreatex.in.fname = fname1;
1977 torture_comment(tctx, "BATCH17: open a file with an batch oplock (share mode: none)\n");
1979 ZERO_STRUCT(break_info);
1980 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1981 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1982 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1984 status = smb_raw_open(cli1->tree, tctx, &io);
1985 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1986 fnum = io.ntcreatex.out.file.fnum;
1987 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1989 torture_comment(tctx, "rename should trigger a break\n");
1990 ZERO_STRUCT(rn);
1991 rn.generic.level = RAW_RENAME_RENAME;
1992 rn.rename.in.pattern1 = fname1;
1993 rn.rename.in.pattern2 = fname2;
1994 rn.rename.in.attrib = 0;
1996 torture_comment(tctx, "trying rename while first file open\n");
1997 status = smb_raw_rename(cli2->tree, &rn);
1998 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2000 torture_wait_for_oplock_break(tctx);
2001 CHECK_VAL(break_info.count, 1);
2002 CHECK_VAL(break_info.failures, 0);
2003 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2005 smbcli_close(cli1->tree, fnum);
2007 done:
2008 smb_raw_exit(cli1->session);
2009 smb_raw_exit(cli2->session);
2010 smbcli_deltree(cli1->tree, BASEDIR);
2011 return ret;
2014 static bool test_raw_oplock_batch18(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2016 const char *fname1 = BASEDIR "\\test_batch18_1.dat";
2017 const char *fname2 = BASEDIR "\\test_batch18_2.dat";
2018 NTSTATUS status;
2019 bool ret = true;
2020 union smb_open io;
2021 union smb_rename rn;
2022 uint16_t fnum=0;
2024 if (!torture_setup_dir(cli1, BASEDIR)) {
2025 return false;
2028 /* cleanup */
2029 smbcli_unlink(cli1->tree, fname1);
2030 smbcli_unlink(cli1->tree, fname2);
2032 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2035 base ntcreatex parms
2037 io.generic.level = RAW_OPEN_NTCREATEX;
2038 io.ntcreatex.in.root_fid = 0;
2039 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2040 io.ntcreatex.in.alloc_size = 0;
2041 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2042 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2043 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2044 io.ntcreatex.in.create_options = 0;
2045 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2046 io.ntcreatex.in.security_flags = 0;
2047 io.ntcreatex.in.fname = fname1;
2049 torture_comment(tctx, "BATCH18: open a file with an batch oplock (share mode: none)\n");
2051 ZERO_STRUCT(break_info);
2052 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2053 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2054 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2056 status = smb_raw_open(cli1->tree, tctx, &io);
2057 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2058 fnum = io.ntcreatex.out.file.fnum;
2059 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2061 torture_comment(tctx, "ntrename should trigger a break\n");
2062 ZERO_STRUCT(rn);
2063 rn.generic.level = RAW_RENAME_NTRENAME;
2064 rn.ntrename.in.attrib = 0;
2065 rn.ntrename.in.flags = RENAME_FLAG_RENAME;
2066 rn.ntrename.in.old_name = fname1;
2067 rn.ntrename.in.new_name = fname2;
2068 torture_comment(tctx, "trying rename while first file open\n");
2069 status = smb_raw_rename(cli2->tree, &rn);
2070 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2072 torture_wait_for_oplock_break(tctx);
2073 CHECK_VAL(break_info.count, 1);
2074 CHECK_VAL(break_info.failures, 0);
2075 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2077 smbcli_close(cli1->tree, fnum);
2079 done:
2080 smb_raw_exit(cli1->session);
2081 smb_raw_exit(cli2->session);
2082 smbcli_deltree(cli1->tree, BASEDIR);
2083 return ret;
2086 static bool test_raw_oplock_batch19(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2088 const char *fname1 = BASEDIR "\\test_batch19_1.dat";
2089 const char *fname2 = BASEDIR "\\test_batch19_2.dat";
2090 const char *fname3 = BASEDIR "\\test_batch19_3.dat";
2091 NTSTATUS status;
2092 bool ret = true;
2093 union smb_open io;
2094 union smb_fileinfo qfi;
2095 union smb_setfileinfo sfi;
2096 uint16_t fnum=0;
2098 if (!torture_setup_dir(cli1, BASEDIR)) {
2099 return false;
2102 /* cleanup */
2103 smbcli_unlink(cli1->tree, fname1);
2104 smbcli_unlink(cli1->tree, fname2);
2105 smbcli_unlink(cli1->tree, fname3);
2107 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2110 base ntcreatex parms
2112 io.generic.level = RAW_OPEN_NTCREATEX;
2113 io.ntcreatex.in.root_fid = 0;
2114 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2115 io.ntcreatex.in.alloc_size = 0;
2116 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2117 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2118 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2119 io.ntcreatex.in.create_options = 0;
2120 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2121 io.ntcreatex.in.security_flags = 0;
2122 io.ntcreatex.in.fname = fname1;
2124 torture_comment(tctx, "BATCH19: open a file with an batch oplock (share mode: none)\n");
2125 ZERO_STRUCT(break_info);
2126 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2127 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2128 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2129 status = smb_raw_open(cli1->tree, tctx, &io);
2130 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2131 fnum = io.ntcreatex.out.file.fnum;
2132 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2134 torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
2135 ZERO_STRUCT(sfi);
2136 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2137 sfi.generic.in.file.path = fname1;
2138 sfi.rename_information.in.overwrite = 0;
2139 sfi.rename_information.in.root_fid = 0;
2140 sfi.rename_information.in.new_name = fname2+strlen(BASEDIR)+1;
2142 status = smb_raw_setpathinfo(cli2->tree, &sfi);
2143 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2145 torture_wait_for_oplock_break(tctx);
2146 CHECK_VAL(break_info.count, 0);
2148 ZERO_STRUCT(qfi);
2149 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2150 qfi.generic.in.file.fnum = fnum;
2152 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2153 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2154 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2156 torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
2157 ZERO_STRUCT(sfi);
2158 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2159 sfi.generic.in.file.fnum = fnum;
2160 sfi.rename_information.in.overwrite = 0;
2161 sfi.rename_information.in.root_fid = 0;
2162 sfi.rename_information.in.new_name = fname3+strlen(BASEDIR)+1;
2164 status = smb_raw_setfileinfo(cli1->tree, &sfi);
2165 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2167 torture_wait_for_oplock_break(tctx);
2168 CHECK_VAL(break_info.count, 0);
2170 ZERO_STRUCT(qfi);
2171 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2172 qfi.generic.in.file.fnum = fnum;
2174 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2175 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2176 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2178 smbcli_close(cli1->tree, fnum);
2180 done:
2181 smb_raw_exit(cli1->session);
2182 smb_raw_exit(cli2->session);
2183 smbcli_deltree(cli1->tree, BASEDIR);
2184 return ret;
2187 /****************************************************
2188 Called from raw-rename - we need oplock handling for
2189 this test so this is why it's in oplock.c, not rename.c
2190 ****************************************************/
2192 bool test_trans2rename(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2194 const char *fname1 = BASEDIR "\\test_trans2rename_1.dat";
2195 const char *fname2 = BASEDIR "\\test_trans2rename_2.dat";
2196 const char *fname3 = BASEDIR "\\test_trans2rename_3.dat";
2197 NTSTATUS status;
2198 bool ret = true;
2199 union smb_open io;
2200 union smb_fileinfo qfi;
2201 union smb_setfileinfo sfi;
2202 uint16_t fnum=0;
2204 if (!torture_setup_dir(cli1, BASEDIR)) {
2205 return false;
2208 /* cleanup */
2209 smbcli_unlink(cli1->tree, fname1);
2210 smbcli_unlink(cli1->tree, fname2);
2211 smbcli_unlink(cli1->tree, fname3);
2213 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2216 base ntcreatex parms
2218 io.generic.level = RAW_OPEN_NTCREATEX;
2219 io.ntcreatex.in.root_fid = 0;
2220 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2221 io.ntcreatex.in.alloc_size = 0;
2222 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2223 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2224 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2225 io.ntcreatex.in.create_options = 0;
2226 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2227 io.ntcreatex.in.security_flags = 0;
2228 io.ntcreatex.in.fname = fname1;
2230 torture_comment(tctx, "open a file with an exclusive oplock (share mode: none)\n");
2231 ZERO_STRUCT(break_info);
2232 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2233 NTCREATEX_FLAGS_REQUEST_OPLOCK;
2234 status = smb_raw_open(cli1->tree, tctx, &io);
2235 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2236 fnum = io.ntcreatex.out.file.fnum;
2237 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
2239 torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
2240 ZERO_STRUCT(sfi);
2241 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2242 sfi.generic.in.file.path = fname1;
2243 sfi.rename_information.in.overwrite = 0;
2244 sfi.rename_information.in.root_fid = 0;
2245 sfi.rename_information.in.new_name = fname2+strlen(BASEDIR)+1;
2247 status = smb_raw_setpathinfo(cli2->tree, &sfi);
2249 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2251 torture_wait_for_oplock_break(tctx);
2252 CHECK_VAL(break_info.count, 0);
2254 ZERO_STRUCT(qfi);
2255 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2256 qfi.generic.in.file.fnum = fnum;
2258 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2259 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2260 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2262 torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
2263 ZERO_STRUCT(sfi);
2264 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2265 sfi.generic.in.file.fnum = fnum;
2266 sfi.rename_information.in.overwrite = 0;
2267 sfi.rename_information.in.root_fid = 0;
2268 sfi.rename_information.in.new_name = fname3+strlen(BASEDIR)+1;
2270 status = smb_raw_setfileinfo(cli1->tree, &sfi);
2271 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2273 torture_wait_for_oplock_break(tctx);
2274 CHECK_VAL(break_info.count, 0);
2276 ZERO_STRUCT(qfi);
2277 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2278 qfi.generic.in.file.fnum = fnum;
2280 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2281 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2282 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2284 smbcli_close(cli1->tree, fnum);
2286 done:
2287 smb_raw_exit(cli1->session);
2288 smb_raw_exit(cli2->session);
2289 smbcli_deltree(cli1->tree, BASEDIR);
2290 return ret;
2293 /****************************************************
2294 Called from raw-rename - we need oplock handling for
2295 this test so this is why it's in oplock.c, not rename.c
2296 ****************************************************/
2298 bool test_nttransrename(struct torture_context *tctx, struct smbcli_state *cli1)
2300 const char *fname1 = BASEDIR "\\test_nttransrename_1.dat";
2301 const char *fname2 = BASEDIR "\\test_nttransrename_2.dat";
2302 NTSTATUS status;
2303 bool ret = true;
2304 union smb_open io;
2305 union smb_fileinfo qfi, qpi;
2306 union smb_rename rn;
2307 uint16_t fnum=0;
2309 if (!torture_setup_dir(cli1, BASEDIR)) {
2310 return false;
2313 /* cleanup */
2314 smbcli_unlink(cli1->tree, fname1);
2315 smbcli_unlink(cli1->tree, fname2);
2317 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2320 base ntcreatex parms
2322 io.generic.level = RAW_OPEN_NTCREATEX;
2323 io.ntcreatex.in.root_fid = 0;
2324 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2325 io.ntcreatex.in.alloc_size = 0;
2326 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2327 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2328 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2329 io.ntcreatex.in.create_options = 0;
2330 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2331 io.ntcreatex.in.security_flags = 0;
2332 io.ntcreatex.in.fname = fname1;
2334 torture_comment(tctx, "nttrans_rename: open a file with an exclusive oplock (share mode: none)\n");
2335 ZERO_STRUCT(break_info);
2336 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2337 NTCREATEX_FLAGS_REQUEST_OPLOCK;
2338 status = smb_raw_open(cli1->tree, tctx, &io);
2339 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2340 fnum = io.ntcreatex.out.file.fnum;
2341 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
2343 torture_comment(tctx, "nttrans_rename: should not trigger a break nor a share mode violation\n");
2344 ZERO_STRUCT(rn);
2345 rn.generic.level = RAW_RENAME_NTTRANS;
2346 rn.nttrans.in.file.fnum = fnum;
2347 rn.nttrans.in.flags = 0;
2348 rn.nttrans.in.new_name = fname2+strlen(BASEDIR)+1;
2350 status = smb_raw_rename(cli1->tree, &rn);
2351 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2353 torture_wait_for_oplock_break(tctx);
2354 CHECK_VAL(break_info.count, 0);
2356 /* w2k3 does nothing, it doesn't rename the file */
2357 torture_comment(tctx, "nttrans_rename: the server should have done nothing\n");
2358 ZERO_STRUCT(qfi);
2359 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2360 qfi.generic.in.file.fnum = fnum;
2362 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2363 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2364 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname1);
2366 ZERO_STRUCT(qpi);
2367 qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2368 qpi.generic.in.file.path = fname1;
2370 status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2371 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2372 CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1);
2374 ZERO_STRUCT(qpi);
2375 qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2376 qpi.generic.in.file.path = fname2;
2378 status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2379 CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2381 torture_comment(tctx, "nttrans_rename: after closing the file the file is still not renamed\n");
2382 status = smbcli_close(cli1->tree, fnum);
2383 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2385 ZERO_STRUCT(qpi);
2386 qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2387 qpi.generic.in.file.path = fname1;
2389 status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2390 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2391 CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1);
2393 ZERO_STRUCT(qpi);
2394 qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2395 qpi.generic.in.file.path = fname2;
2397 status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2398 CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2400 torture_comment(tctx, "nttrans_rename: rename with an invalid handle gives NT_STATUS_INVALID_HANDLE\n");
2401 ZERO_STRUCT(rn);
2402 rn.generic.level = RAW_RENAME_NTTRANS;
2403 rn.nttrans.in.file.fnum = fnum+1;
2404 rn.nttrans.in.flags = 0;
2405 rn.nttrans.in.new_name = fname2+strlen(BASEDIR)+1;
2407 status = smb_raw_rename(cli1->tree, &rn);
2409 CHECK_STATUS(tctx, status, NT_STATUS_INVALID_HANDLE);
2411 done:
2412 smb_raw_exit(cli1->session);
2413 smbcli_deltree(cli1->tree, BASEDIR);
2414 return ret;
2418 static bool test_raw_oplock_batch20(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2420 const char *fname1 = BASEDIR "\\test_batch20_1.dat";
2421 const char *fname2 = BASEDIR "\\test_batch20_2.dat";
2422 const char *fname3 = BASEDIR "\\test_batch20_3.dat";
2423 NTSTATUS status;
2424 bool ret = true;
2425 union smb_open io;
2426 union smb_fileinfo qfi;
2427 union smb_setfileinfo sfi;
2428 uint16_t fnum=0,fnum2=0;
2430 if (!torture_setup_dir(cli1, BASEDIR)) {
2431 return false;
2434 /* cleanup */
2435 smbcli_unlink(cli1->tree, fname1);
2436 smbcli_unlink(cli1->tree, fname2);
2437 smbcli_unlink(cli1->tree, fname3);
2439 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2442 base ntcreatex parms
2444 io.generic.level = RAW_OPEN_NTCREATEX;
2445 io.ntcreatex.in.root_fid = 0;
2446 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2447 io.ntcreatex.in.alloc_size = 0;
2448 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2449 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2450 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2451 io.ntcreatex.in.create_options = 0;
2452 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2453 io.ntcreatex.in.security_flags = 0;
2454 io.ntcreatex.in.fname = fname1;
2456 torture_comment(tctx, "BATCH20: open a file with an batch oplock (share mode: all)\n");
2457 ZERO_STRUCT(break_info);
2458 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2459 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2460 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2461 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2462 NTCREATEX_SHARE_ACCESS_WRITE|
2463 NTCREATEX_SHARE_ACCESS_DELETE;
2464 status = smb_raw_open(cli1->tree, tctx, &io);
2465 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2466 fnum = io.ntcreatex.out.file.fnum;
2467 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2469 torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
2470 ZERO_STRUCT(sfi);
2471 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2472 sfi.generic.in.file.path = fname1;
2473 sfi.rename_information.in.overwrite = 0;
2474 sfi.rename_information.in.root_fid = 0;
2475 sfi.rename_information.in.new_name = fname2+strlen(BASEDIR)+1;
2477 status = smb_raw_setpathinfo(cli2->tree, &sfi);
2478 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2480 torture_wait_for_oplock_break(tctx);
2481 CHECK_VAL(break_info.count, 0);
2483 ZERO_STRUCT(qfi);
2484 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2485 qfi.generic.in.file.fnum = fnum;
2487 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2488 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2489 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2491 torture_comment(tctx, "open a file with the new name an batch oplock (share mode: all)\n");
2492 ZERO_STRUCT(break_info);
2493 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2494 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2495 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2496 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2497 NTCREATEX_SHARE_ACCESS_WRITE|
2498 NTCREATEX_SHARE_ACCESS_DELETE;
2499 io.ntcreatex.in.fname = fname2;
2500 status = smb_raw_open(cli2->tree, tctx, &io);
2501 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2502 fnum2 = io.ntcreatex.out.file.fnum;
2503 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2505 torture_wait_for_oplock_break(tctx);
2506 CHECK_VAL(break_info.count, 1);
2507 CHECK_VAL(break_info.failures, 0);
2508 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2510 torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
2511 ZERO_STRUCT(sfi);
2512 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2513 sfi.generic.in.file.fnum = fnum;
2514 sfi.rename_information.in.overwrite = 0;
2515 sfi.rename_information.in.root_fid = 0;
2516 sfi.rename_information.in.new_name = fname3+strlen(BASEDIR)+1;
2518 status = smb_raw_setfileinfo(cli1->tree, &sfi);
2519 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2521 torture_wait_for_oplock_break(tctx);
2522 CHECK_VAL(break_info.count, 1);
2523 CHECK_VAL(break_info.failures, 0);
2524 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2526 ZERO_STRUCT(qfi);
2527 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2528 qfi.generic.in.file.fnum = fnum;
2530 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2531 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2532 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2534 ZERO_STRUCT(qfi);
2535 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2536 qfi.generic.in.file.fnum = fnum2;
2538 status = smb_raw_fileinfo(cli2->tree, tctx, &qfi);
2539 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2540 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2542 smbcli_close(cli1->tree, fnum);
2544 done:
2545 smb_raw_exit(cli1->session);
2546 smb_raw_exit(cli2->session);
2547 smbcli_deltree(cli1->tree, BASEDIR);
2548 return ret;
2551 static bool test_raw_oplock_batch21(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2553 const char *fname = BASEDIR "\\test_batch21.dat";
2554 NTSTATUS status;
2555 bool ret = true;
2556 union smb_open io;
2557 struct smb_echo e;
2558 uint16_t fnum=0;
2559 char c = 0;
2560 ssize_t wr;
2562 if (!torture_setup_dir(cli1, BASEDIR)) {
2563 return false;
2566 /* cleanup */
2567 smbcli_unlink(cli1->tree, fname);
2569 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2572 base ntcreatex parms
2574 io.generic.level = RAW_OPEN_NTCREATEX;
2575 io.ntcreatex.in.root_fid = 0;
2576 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2577 io.ntcreatex.in.alloc_size = 0;
2578 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2579 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2580 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2581 io.ntcreatex.in.create_options = 0;
2582 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2583 io.ntcreatex.in.security_flags = 0;
2584 io.ntcreatex.in.fname = fname;
2587 with a batch oplock we get a break
2589 torture_comment(tctx, "BATCH21: open with batch oplock\n");
2590 ZERO_STRUCT(break_info);
2591 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2592 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2593 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2594 status = smb_raw_open(cli1->tree, tctx, &io);
2595 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2596 fnum = io.ntcreatex.out.file.fnum;
2597 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2599 torture_comment(tctx, "writing should not generate a break\n");
2600 wr = smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
2601 CHECK_VAL(wr, 1);
2602 CHECK_STATUS(tctx, smbcli_nt_error(cli1->tree), NT_STATUS_OK);
2604 ZERO_STRUCT(e);
2605 e.in.repeat_count = 1;
2606 status = smb_raw_echo(cli1->transport, &e);
2607 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2609 torture_wait_for_oplock_break(tctx);
2610 CHECK_VAL(break_info.count, 0);
2612 smbcli_close(cli1->tree, fnum);
2614 done:
2615 smb_raw_exit(cli1->session);
2616 smb_raw_exit(cli2->session);
2617 smbcli_deltree(cli1->tree, BASEDIR);
2618 return ret;
2621 static bool test_raw_oplock_batch22(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2623 const char *fname = BASEDIR "\\test_batch22.dat";
2624 NTSTATUS status;
2625 bool ret = true;
2626 union smb_open io;
2627 uint16_t fnum=0, fnum2=0;
2628 struct timeval tv;
2629 int timeout = torture_setting_int(tctx, "oplocktimeout", 30);
2630 int te;
2632 if (torture_setting_bool(tctx, "samba3", false)) {
2633 torture_skip(tctx, "BATCH22 disabled against samba3\n");
2636 if (!torture_setup_dir(cli1, BASEDIR)) {
2637 return false;
2640 /* cleanup */
2641 smbcli_unlink(cli1->tree, fname);
2643 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2646 base ntcreatex parms
2648 io.generic.level = RAW_OPEN_NTCREATEX;
2649 io.ntcreatex.in.root_fid = 0;
2650 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2651 io.ntcreatex.in.alloc_size = 0;
2652 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2653 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2654 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2655 io.ntcreatex.in.create_options = 0;
2656 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2657 io.ntcreatex.in.security_flags = 0;
2658 io.ntcreatex.in.fname = fname;
2661 with a batch oplock we get a break
2663 torture_comment(tctx, "BATCH22: open with batch oplock\n");
2664 ZERO_STRUCT(break_info);
2665 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2666 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2667 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2668 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2669 NTCREATEX_SHARE_ACCESS_WRITE|
2670 NTCREATEX_SHARE_ACCESS_DELETE;
2671 status = smb_raw_open(cli1->tree, tctx, &io);
2672 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2673 fnum = io.ntcreatex.out.file.fnum;
2674 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2676 torture_comment(tctx, "a 2nd open should not succeed after the oplock "
2677 "break timeout\n");
2678 tv = timeval_current();
2679 smbcli_oplock_handler(cli1->transport, oplock_handler_timeout, cli1->tree);
2680 status = smb_raw_open(cli1->tree, tctx, &io);
2681 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2682 torture_wait_for_oplock_break(tctx);
2683 te = (int)timeval_elapsed(&tv);
2684 CHECK_RANGE(te, timeout - 1, timeout + 15);
2686 CHECK_VAL(break_info.count, 1);
2687 CHECK_VAL(break_info.fnum, fnum);
2688 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2689 CHECK_VAL(break_info.failures, 0);
2690 ZERO_STRUCT(break_info);
2692 torture_comment(tctx, "a 2nd open should succeed after the oplock "
2693 "release without break\n");
2694 tv = timeval_current();
2695 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2696 status = smb_raw_open(cli1->tree, tctx, &io);
2697 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2698 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2699 torture_wait_for_oplock_break(tctx);
2700 te = (int)timeval_elapsed(&tv);
2701 /* it should come in without delay */
2702 CHECK_RANGE(te+1, 0, timeout);
2703 fnum2 = io.ntcreatex.out.file.fnum;
2705 CHECK_VAL(break_info.count, 0);
2707 smbcli_close(cli1->tree, fnum);
2708 smbcli_close(cli1->tree, fnum2);
2710 done:
2711 smb_raw_exit(cli1->session);
2712 smb_raw_exit(cli2->session);
2713 smbcli_deltree(cli1->tree, BASEDIR);
2714 return ret;
2717 static bool test_raw_oplock_batch23(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2719 const char *fname = BASEDIR "\\test_batch23.dat";
2720 NTSTATUS status;
2721 bool ret = true;
2722 union smb_open io;
2723 uint16_t fnum=0, fnum2=0,fnum3=0;
2724 struct smbcli_state *cli3 = NULL;
2726 if (!torture_setup_dir(cli1, BASEDIR)) {
2727 return false;
2730 /* cleanup */
2731 smbcli_unlink(cli1->tree, fname);
2733 ret = open_connection_no_level2_oplocks(tctx, &cli3);
2734 CHECK_VAL(ret, true);
2736 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2737 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
2738 smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
2741 base ntcreatex parms
2743 io.generic.level = RAW_OPEN_NTCREATEX;
2744 io.ntcreatex.in.root_fid = 0;
2745 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2746 io.ntcreatex.in.alloc_size = 0;
2747 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2748 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2749 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2750 io.ntcreatex.in.create_options = 0;
2751 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2752 io.ntcreatex.in.security_flags = 0;
2753 io.ntcreatex.in.fname = fname;
2755 torture_comment(tctx, "BATCH23: a open and ask for a batch oplock\n");
2756 ZERO_STRUCT(break_info);
2758 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
2759 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
2760 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2761 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2762 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2763 status = smb_raw_open(cli1->tree, tctx, &io);
2764 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2765 fnum = io.ntcreatex.out.file.fnum;
2766 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2768 ZERO_STRUCT(break_info);
2770 torture_comment(tctx, "a 2nd open without level2 oplock support should generate a break to level2\n");
2771 status = smb_raw_open(cli3->tree, tctx, &io);
2772 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2773 fnum3 = io.ntcreatex.out.file.fnum;
2774 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
2776 torture_wait_for_oplock_break(tctx);
2777 CHECK_VAL(break_info.count, 1);
2778 CHECK_VAL(break_info.fnum, fnum);
2779 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2780 CHECK_VAL(break_info.failures, 0);
2782 ZERO_STRUCT(break_info);
2784 torture_comment(tctx, "a 3rd open with level2 oplock support should not generate a break\n");
2785 status = smb_raw_open(cli2->tree, tctx, &io);
2786 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2787 fnum2 = io.ntcreatex.out.file.fnum;
2788 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2790 torture_wait_for_oplock_break(tctx);
2791 CHECK_VAL(break_info.count, 0);
2793 smbcli_close(cli1->tree, fnum);
2794 smbcli_close(cli2->tree, fnum2);
2795 smbcli_close(cli3->tree, fnum3);
2797 done:
2798 smb_raw_exit(cli1->session);
2799 smb_raw_exit(cli2->session);
2800 smb_raw_exit(cli3->session);
2801 smbcli_deltree(cli1->tree, BASEDIR);
2802 return ret;
2805 static bool test_raw_oplock_batch24(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2807 const char *fname = BASEDIR "\\test_batch24.dat";
2808 NTSTATUS status;
2809 bool ret = true;
2810 union smb_open io;
2811 uint16_t fnum2=0,fnum3=0;
2812 struct smbcli_state *cli3 = NULL;
2814 if (!torture_setup_dir(cli1, BASEDIR)) {
2815 return false;
2818 /* cleanup */
2819 smbcli_unlink(cli1->tree, fname);
2821 ret = open_connection_no_level2_oplocks(tctx, &cli3);
2822 CHECK_VAL(ret, true);
2824 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2825 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
2826 smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
2829 base ntcreatex parms
2831 io.generic.level = RAW_OPEN_NTCREATEX;
2832 io.ntcreatex.in.root_fid = 0;
2833 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2834 io.ntcreatex.in.alloc_size = 0;
2835 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2836 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2837 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2838 io.ntcreatex.in.create_options = 0;
2839 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2840 io.ntcreatex.in.security_flags = 0;
2841 io.ntcreatex.in.fname = fname;
2843 torture_comment(tctx, "BATCH24: a open without level support and ask for a batch oplock\n");
2844 ZERO_STRUCT(break_info);
2846 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
2847 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
2848 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2849 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2850 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2851 status = smb_raw_open(cli3->tree, tctx, &io);
2852 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2853 fnum3 = io.ntcreatex.out.file.fnum;
2854 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2856 ZERO_STRUCT(break_info);
2858 torture_comment(tctx, "a 2nd open with level2 oplock support should generate a break to none\n");
2859 status = smb_raw_open(cli2->tree, tctx, &io);
2860 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2861 fnum2 = io.ntcreatex.out.file.fnum;
2862 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2864 torture_wait_for_oplock_break(tctx);
2865 CHECK_VAL(break_info.count, 1);
2866 CHECK_VAL(break_info.fnum, fnum3);
2867 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
2868 CHECK_VAL(break_info.failures, 0);
2870 smbcli_close(cli3->tree, fnum3);
2871 smbcli_close(cli2->tree, fnum2);
2873 done:
2874 smb_raw_exit(cli1->session);
2875 smb_raw_exit(cli2->session);
2876 smb_raw_exit(cli3->session);
2877 smbcli_deltree(cli1->tree, BASEDIR);
2878 return ret;
2881 static bool test_raw_oplock_batch25(struct torture_context *tctx,
2882 struct smbcli_state *cli1,
2883 struct smbcli_state *cli2)
2885 const char *fname = BASEDIR "\\test_batch25.dat";
2886 NTSTATUS status;
2887 bool ret = true;
2888 union smb_open io;
2889 union smb_setfileinfo sfi;
2890 uint16_t fnum=0;
2892 if (!torture_setup_dir(cli1, BASEDIR)) {
2893 return false;
2896 /* cleanup */
2897 smbcli_unlink(cli1->tree, fname);
2899 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2902 base ntcreatex parms
2904 io.generic.level = RAW_OPEN_NTCREATEX;
2905 io.ntcreatex.in.root_fid = 0;
2906 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2907 io.ntcreatex.in.alloc_size = 0;
2908 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2909 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2910 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2911 io.ntcreatex.in.create_options = 0;
2912 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2913 io.ntcreatex.in.security_flags = 0;
2914 io.ntcreatex.in.fname = fname;
2916 torture_comment(tctx, "BATCH25: open a file with an batch oplock "
2917 "(share mode: none)\n");
2919 ZERO_STRUCT(break_info);
2920 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2921 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2922 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2923 status = smb_raw_open(cli1->tree, tctx, &io);
2924 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2925 fnum = io.ntcreatex.out.file.fnum;
2926 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2928 torture_comment(tctx, "setpathinfo attribute info should not trigger "
2929 "a break nor a violation\n");
2930 ZERO_STRUCT(sfi);
2931 sfi.generic.level = RAW_SFILEINFO_SETATTR;
2932 sfi.generic.in.file.path = fname;
2933 sfi.setattr.in.attrib = FILE_ATTRIBUTE_HIDDEN;
2934 sfi.setattr.in.write_time = 0;
2936 status = smb_raw_setpathinfo(cli2->tree, &sfi);
2937 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2939 torture_wait_for_oplock_break(tctx);
2940 CHECK_VAL(break_info.count, 0);
2942 smbcli_close(cli1->tree, fnum);
2944 done:
2945 smb_raw_exit(cli1->session);
2946 smb_raw_exit(cli2->session);
2947 smbcli_deltree(cli1->tree, BASEDIR);
2948 return ret;
2951 /* Test how oplocks work on streams. */
2952 static bool test_raw_oplock_stream1(struct torture_context *tctx,
2953 struct smbcli_state *cli1,
2954 struct smbcli_state *cli2)
2956 NTSTATUS status;
2957 union smb_open io;
2958 const char *fname_base = BASEDIR "\\test_stream1.txt";
2959 const char *stream = "Stream One:$DATA";
2960 const char *fname_stream, *fname_default_stream;
2961 const char *default_stream = "::$DATA";
2962 bool ret = true;
2963 int fnum = -1;
2964 int i;
2965 int stream_fnum = -1;
2966 uint32_t batch_req = NTCREATEX_FLAGS_REQUEST_OPLOCK |
2967 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK | NTCREATEX_FLAGS_EXTENDED;
2968 uint32_t exclusive_req = NTCREATEX_FLAGS_REQUEST_OPLOCK |
2969 NTCREATEX_FLAGS_EXTENDED;
2970 /* Try some permutations of taking oplocks on streams. */
2971 #define NSTREAM_OPLOCK_RESULTS 8
2972 struct {
2973 const char *fname;
2974 bool open_base_file;
2975 uint32_t oplock_req;
2976 uint32_t oplock_granted;
2977 } stream_oplock_results[NSTREAM_OPLOCK_RESULTS] = {
2978 /* Request oplock on stream without the base file open. */
2979 {fname_stream, false, batch_req, NO_OPLOCK_RETURN},
2980 {fname_default_stream, false, batch_req, NO_OPLOCK_RETURN},
2981 {fname_stream, false, exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
2982 {fname_default_stream, false, exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
2984 /* Request oplock on stream with the base file open. */
2985 {fname_stream, true, batch_req, NO_OPLOCK_RETURN},
2986 {fname_default_stream, true, batch_req, NO_OPLOCK_RETURN},
2987 {fname_stream, true, exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
2988 {fname_default_stream, true, exclusive_req, LEVEL_II_OPLOCK_RETURN},
2993 /* Only passes against windows at the moment. */
2994 if (torture_setting_bool(tctx, "samba3", false) ||
2995 torture_setting_bool(tctx, "samba4", false)) {
2996 torture_skip(tctx, "STREAM1 disabled against samba3+4\n");
2999 fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
3000 fname_default_stream = talloc_asprintf(tctx, "%s%s", fname_base,
3001 default_stream);
3003 if (!torture_setup_dir(cli1, BASEDIR)) {
3004 return false;
3006 smbcli_unlink(cli1->tree, fname_base);
3008 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3009 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
3011 /* Setup generic open parameters. */
3012 io.generic.level = RAW_OPEN_NTCREATEX;
3013 io.ntcreatex.in.root_fid = 0;
3014 io.ntcreatex.in.access_mask = (SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA|
3015 SEC_FILE_APPEND_DATA|SEC_STD_READ_CONTROL);
3016 io.ntcreatex.in.create_options = 0;
3017 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3018 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3019 NTCREATEX_SHARE_ACCESS_WRITE;
3020 io.ntcreatex.in.alloc_size = 0;
3021 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3022 io.ntcreatex.in.security_flags = 0;
3024 /* Create the file with a stream */
3025 io.ntcreatex.in.fname = fname_stream;
3026 io.ntcreatex.in.flags = 0;
3027 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
3028 status = smb_raw_open(cli1->tree, tctx, &io);
3029 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3030 smbcli_close(cli1->tree, io.ntcreatex.out.file.fnum);
3032 /* Change the disposition to open now that the file has been created. */
3033 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
3035 for (i = 0; i < NSTREAM_OPLOCK_RESULTS; i++) {
3036 const char *fname = stream_oplock_results[i].fname;
3037 bool open_base_file = stream_oplock_results[i].open_base_file;
3038 uint32_t oplock_req = stream_oplock_results[i].oplock_req;
3039 uint32_t oplock_granted =
3040 stream_oplock_results[i].oplock_granted;
3041 int base_fnum = -1;
3043 if (open_base_file) {
3044 torture_comment(tctx, "Opening base file: %s with "
3045 "%d\n", fname_base, oplock_req);
3046 io.ntcreatex.in.fname = fname_base;
3047 io.ntcreatex.in.flags = batch_req;
3048 status = smb_raw_open(cli2->tree, tctx, &io);
3049 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3050 CHECK_VAL(io.ntcreatex.out.oplock_level,
3051 BATCH_OPLOCK_RETURN);
3052 base_fnum = io.ntcreatex.out.file.fnum;
3055 torture_comment(tctx, "%d: Opening stream: %s with %d\n", i,
3056 fname, oplock_req);
3057 io.ntcreatex.in.fname = fname;
3058 io.ntcreatex.in.flags = oplock_req;
3060 /* Do the open with the desired oplock on the stream. */
3061 status = smb_raw_open(cli1->tree, tctx, &io);
3062 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3063 CHECK_VAL(io.ntcreatex.out.oplock_level, oplock_granted);
3064 smbcli_close(cli1->tree, io.ntcreatex.out.file.fnum);
3066 /* Cleanup the base file if it was opened. */
3067 if (base_fnum != -1) {
3068 smbcli_close(cli2->tree, base_fnum);
3072 /* Open the stream with an exclusive oplock. */
3073 torture_comment(tctx, "Opening stream: %s with %d\n",
3074 fname_stream, exclusive_req);
3075 io.ntcreatex.in.fname = fname_stream;
3076 io.ntcreatex.in.flags = exclusive_req;
3077 status = smb_raw_open(cli1->tree, tctx, &io);
3078 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3079 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
3080 stream_fnum = io.ntcreatex.out.file.fnum;
3082 /* Open the base file and see if it contends. */
3083 ZERO_STRUCT(break_info);
3084 torture_comment(tctx, "Opening base file: %s with "
3085 "%d\n", fname_base, batch_req);
3086 io.ntcreatex.in.fname = fname_base;
3087 io.ntcreatex.in.flags = batch_req;
3088 status = smb_raw_open(cli2->tree, tctx, &io);
3089 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3090 CHECK_VAL(io.ntcreatex.out.oplock_level,
3091 BATCH_OPLOCK_RETURN);
3092 smbcli_close(cli2->tree, io.ntcreatex.out.file.fnum);
3094 torture_wait_for_oplock_break(tctx);
3095 CHECK_VAL(break_info.count, 0);
3096 CHECK_VAL(break_info.failures, 0);
3098 /* Open the stream again to see if it contends. */
3099 ZERO_STRUCT(break_info);
3100 torture_comment(tctx, "Opening stream again: %s with "
3101 "%d\n", fname_base, batch_req);
3102 io.ntcreatex.in.fname = fname_stream;
3103 io.ntcreatex.in.flags = exclusive_req;
3104 status = smb_raw_open(cli2->tree, tctx, &io);
3105 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3106 CHECK_VAL(io.ntcreatex.out.oplock_level,
3107 LEVEL_II_OPLOCK_RETURN);
3108 smbcli_close(cli2->tree, io.ntcreatex.out.file.fnum);
3110 torture_wait_for_oplock_break(tctx);
3111 CHECK_VAL(break_info.count, 1);
3112 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3113 CHECK_VAL(break_info.failures, 0);
3115 /* Close the stream. */
3116 if (stream_fnum != -1) {
3117 smbcli_close(cli1->tree, stream_fnum);
3120 done:
3121 smbcli_close(cli1->tree, fnum);
3122 smb_raw_exit(cli1->session);
3123 smb_raw_exit(cli2->session);
3124 smbcli_deltree(cli1->tree, BASEDIR);
3125 return ret;
3128 static bool test_raw_oplock_doc(struct torture_context *tctx,
3129 struct smbcli_state *cli)
3131 const char *fname = BASEDIR "\\test_oplock_doc.dat";
3132 NTSTATUS status;
3133 bool ret = true;
3134 union smb_open io;
3135 uint16_t fnum=0;
3137 if (!torture_setup_dir(cli, BASEDIR)) {
3138 return false;
3141 /* cleanup */
3142 smbcli_unlink(cli->tree, fname);
3144 smbcli_oplock_handler(cli->transport, oplock_handler_ack_to_given,
3145 cli->tree);
3148 base ntcreatex parms
3150 io.generic.level = RAW_OPEN_NTCREATEX;
3151 io.ntcreatex.in.root_fid = 0;
3152 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3153 io.ntcreatex.in.alloc_size = 0;
3154 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3155 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3156 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3157 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
3158 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3159 io.ntcreatex.in.security_flags = 0;
3160 io.ntcreatex.in.fname = fname;
3162 torture_comment(tctx, "open a delete-on-close file with a batch "
3163 "oplock\n");
3164 ZERO_STRUCT(break_info);
3165 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3166 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3167 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3169 status = smb_raw_open(cli->tree, tctx, &io);
3170 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3171 fnum = io.ntcreatex.out.file.fnum;
3172 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3174 smbcli_close(cli->tree, fnum);
3176 done:
3177 smb_raw_exit(cli->session);
3178 smbcli_deltree(cli->tree, BASEDIR);
3179 return ret;
3182 /* Open a file with a batch oplock, then open it again from a second client
3183 * requesting no oplock. Having two open file handles should break our own
3184 * oplock during BRL acquisition.
3186 static bool test_raw_oplock_brl1(struct torture_context *tctx,
3187 struct smbcli_state *cli1,
3188 struct smbcli_state *cli2)
3190 const char *fname = BASEDIR "\\test_batch_brl.dat";
3191 /*int fname, f;*/
3192 bool ret = true;
3193 uint8_t buf[1000];
3194 bool correct = true;
3195 union smb_open io;
3196 NTSTATUS status;
3197 uint16_t fnum=0;
3198 uint16_t fnum2=0;
3200 if (!torture_setup_dir(cli1, BASEDIR)) {
3201 return false;
3204 /* cleanup */
3205 smbcli_unlink(cli1->tree, fname);
3207 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3208 cli1->tree);
3211 base ntcreatex parms
3213 io.generic.level = RAW_OPEN_NTCREATEX;
3214 io.ntcreatex.in.root_fid = 0;
3215 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3216 SEC_RIGHTS_FILE_WRITE;
3217 io.ntcreatex.in.alloc_size = 0;
3218 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3219 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3220 NTCREATEX_SHARE_ACCESS_WRITE;
3221 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3222 io.ntcreatex.in.create_options = 0;
3223 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3224 io.ntcreatex.in.security_flags = 0;
3225 io.ntcreatex.in.fname = fname;
3228 with a batch oplock we get a break
3230 torture_comment(tctx, "open with batch oplock\n");
3231 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3232 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3233 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3235 status = smb_raw_open(cli1->tree, tctx, &io);
3236 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3237 fnum = io.ntcreatex.out.file.fnum;
3238 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3239 /* create a file with bogus data */
3240 memset(buf, 0, sizeof(buf));
3242 if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
3243 sizeof(buf))
3245 torture_comment(tctx, "Failed to create file\n");
3246 correct = false;
3247 goto done;
3250 torture_comment(tctx, "a 2nd open should give a break\n");
3251 ZERO_STRUCT(break_info);
3253 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
3254 status = smb_raw_open(cli2->tree, tctx, &io);
3255 fnum2 = io.ntcreatex.out.file.fnum;
3256 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3257 CHECK_VAL(break_info.count, 1);
3258 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3259 CHECK_VAL(break_info.failures, 0);
3260 CHECK_VAL(break_info.fnum, fnum);
3262 ZERO_STRUCT(break_info);
3264 torture_comment(tctx, "a self BRL acquisition should break to none\n");
3266 status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
3267 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3269 torture_wait_for_oplock_break(tctx);
3270 CHECK_VAL(break_info.count, 1);
3271 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
3272 CHECK_VAL(break_info.fnum, fnum);
3273 CHECK_VAL(break_info.failures, 0);
3275 /* expect no oplock break */
3276 ZERO_STRUCT(break_info);
3277 status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
3278 CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
3280 torture_wait_for_oplock_break(tctx);
3281 CHECK_VAL(break_info.count, 0);
3282 CHECK_VAL(break_info.level, 0);
3283 CHECK_VAL(break_info.fnum, 0);
3284 CHECK_VAL(break_info.failures, 0);
3286 smbcli_close(cli1->tree, fnum);
3287 smbcli_close(cli2->tree, fnum2);
3289 done:
3290 smb_raw_exit(cli1->session);
3291 smb_raw_exit(cli2->session);
3292 smbcli_deltree(cli1->tree, BASEDIR);
3293 return ret;
3297 /* Open a file with a batch oplock on one client and then acquire a brl.
3298 * We should not contend our own oplock.
3300 static bool test_raw_oplock_brl2(struct torture_context *tctx, struct smbcli_state *cli1)
3302 const char *fname = BASEDIR "\\test_batch_brl.dat";
3303 /*int fname, f;*/
3304 bool ret = true;
3305 uint8_t buf[1000];
3306 bool correct = true;
3307 union smb_open io;
3308 NTSTATUS status;
3309 uint16_t fnum=0;
3311 if (!torture_setup_dir(cli1, BASEDIR)) {
3312 return false;
3315 /* cleanup */
3316 smbcli_unlink(cli1->tree, fname);
3318 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3319 cli1->tree);
3322 base ntcreatex parms
3324 io.generic.level = RAW_OPEN_NTCREATEX;
3325 io.ntcreatex.in.root_fid = 0;
3326 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3327 SEC_RIGHTS_FILE_WRITE;
3328 io.ntcreatex.in.alloc_size = 0;
3329 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3330 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3331 NTCREATEX_SHARE_ACCESS_WRITE;
3332 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3333 io.ntcreatex.in.create_options = 0;
3334 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3335 io.ntcreatex.in.security_flags = 0;
3336 io.ntcreatex.in.fname = fname;
3339 with a batch oplock we get a break
3341 torture_comment(tctx, "open with batch oplock\n");
3342 ZERO_STRUCT(break_info);
3343 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3344 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3345 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3347 status = smb_raw_open(cli1->tree, tctx, &io);
3348 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3349 fnum = io.ntcreatex.out.file.fnum;
3350 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3352 /* create a file with bogus data */
3353 memset(buf, 0, sizeof(buf));
3355 if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
3356 sizeof(buf))
3358 torture_comment(tctx, "Failed to create file\n");
3359 correct = false;
3360 goto done;
3363 torture_comment(tctx, "a self BRL acquisition should not break to "
3364 "none\n");
3366 status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
3367 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3369 status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
3370 CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
3372 /* With one file handle open a BRL should not contend our oplock.
3373 * Thus, no oplock break will be received and the entire break_info
3374 * struct will be 0 */
3375 torture_wait_for_oplock_break(tctx);
3376 CHECK_VAL(break_info.fnum, 0);
3377 CHECK_VAL(break_info.count, 0);
3378 CHECK_VAL(break_info.level, 0);
3379 CHECK_VAL(break_info.failures, 0);
3381 smbcli_close(cli1->tree, fnum);
3383 done:
3384 smb_raw_exit(cli1->session);
3385 smbcli_deltree(cli1->tree, BASEDIR);
3386 return ret;
3389 /* Open a file with a batch oplock twice from one client and then acquire a
3390 * brl. BRL acquisition should break our own oplock.
3392 static bool test_raw_oplock_brl3(struct torture_context *tctx,
3393 struct smbcli_state *cli1)
3395 const char *fname = BASEDIR "\\test_batch_brl.dat";
3396 bool ret = true;
3397 uint8_t buf[1000];
3398 bool correct = true;
3399 union smb_open io;
3400 NTSTATUS status;
3401 uint16_t fnum=0;
3402 uint16_t fnum2=0;
3404 if (!torture_setup_dir(cli1, BASEDIR)) {
3405 return false;
3408 /* cleanup */
3409 smbcli_unlink(cli1->tree, fname);
3411 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3412 cli1->tree);
3415 base ntcreatex parms
3417 io.generic.level = RAW_OPEN_NTCREATEX;
3418 io.ntcreatex.in.root_fid = 0;
3419 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3420 SEC_RIGHTS_FILE_WRITE;
3421 io.ntcreatex.in.alloc_size = 0;
3422 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3423 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3424 NTCREATEX_SHARE_ACCESS_WRITE;
3425 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3426 io.ntcreatex.in.create_options = 0;
3427 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3428 io.ntcreatex.in.security_flags = 0;
3429 io.ntcreatex.in.fname = fname;
3432 with a batch oplock we get a break
3434 torture_comment(tctx, "open with batch oplock\n");
3435 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3436 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3437 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3439 status = smb_raw_open(cli1->tree, tctx, &io);
3440 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3441 fnum = io.ntcreatex.out.file.fnum;
3442 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3444 /* create a file with bogus data */
3445 memset(buf, 0, sizeof(buf));
3447 if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
3448 sizeof(buf))
3450 torture_comment(tctx, "Failed to create file\n");
3451 correct = false;
3452 goto done;
3455 torture_comment(tctx, "a 2nd open should give a break\n");
3456 ZERO_STRUCT(break_info);
3458 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
3459 status = smb_raw_open(cli1->tree, tctx, &io);
3460 fnum2 = io.ntcreatex.out.file.fnum;
3461 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3462 CHECK_VAL(break_info.count, 1);
3463 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3464 CHECK_VAL(break_info.failures, 0);
3465 CHECK_VAL(break_info.fnum, fnum);
3467 ZERO_STRUCT(break_info);
3469 torture_comment(tctx, "a self BRL acquisition should break to none\n");
3471 status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
3472 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3474 torture_wait_for_oplock_break(tctx);
3475 CHECK_VAL(break_info.count, 1);
3476 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
3477 CHECK_VAL(break_info.fnum, fnum);
3478 CHECK_VAL(break_info.failures, 0);
3480 /* expect no oplock break */
3481 ZERO_STRUCT(break_info);
3482 status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
3483 CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
3485 torture_wait_for_oplock_break(tctx);
3486 CHECK_VAL(break_info.count, 0);
3487 CHECK_VAL(break_info.level, 0);
3488 CHECK_VAL(break_info.fnum, 0);
3489 CHECK_VAL(break_info.failures, 0);
3491 smbcli_close(cli1->tree, fnum);
3492 smbcli_close(cli1->tree, fnum2);
3494 done:
3495 smb_raw_exit(cli1->session);
3496 smbcli_deltree(cli1->tree, BASEDIR);
3497 return ret;
3501 basic testing of oplocks
3503 struct torture_suite *torture_raw_oplock(TALLOC_CTX *mem_ctx)
3505 struct torture_suite *suite = torture_suite_create(mem_ctx, "OPLOCK");
3507 torture_suite_add_2smb_test(suite, "EXCLUSIVE1", test_raw_oplock_exclusive1);
3508 torture_suite_add_2smb_test(suite, "EXCLUSIVE2", test_raw_oplock_exclusive2);
3509 torture_suite_add_2smb_test(suite, "EXCLUSIVE3", test_raw_oplock_exclusive3);
3510 torture_suite_add_2smb_test(suite, "EXCLUSIVE4", test_raw_oplock_exclusive4);
3511 torture_suite_add_2smb_test(suite, "EXCLUSIVE5", test_raw_oplock_exclusive5);
3512 torture_suite_add_2smb_test(suite, "EXCLUSIVE6", test_raw_oplock_exclusive6);
3513 torture_suite_add_2smb_test(suite, "BATCH1", test_raw_oplock_batch1);
3514 torture_suite_add_2smb_test(suite, "BATCH2", test_raw_oplock_batch2);
3515 torture_suite_add_2smb_test(suite, "BATCH3", test_raw_oplock_batch3);
3516 torture_suite_add_2smb_test(suite, "BATCH4", test_raw_oplock_batch4);
3517 torture_suite_add_2smb_test(suite, "BATCH5", test_raw_oplock_batch5);
3518 torture_suite_add_2smb_test(suite, "BATCH6", test_raw_oplock_batch6);
3519 torture_suite_add_2smb_test(suite, "BATCH7", test_raw_oplock_batch7);
3520 torture_suite_add_2smb_test(suite, "BATCH8", test_raw_oplock_batch8);
3521 torture_suite_add_2smb_test(suite, "BATCH9", test_raw_oplock_batch9);
3522 torture_suite_add_2smb_test(suite, "BATCH10", test_raw_oplock_batch10);
3523 torture_suite_add_2smb_test(suite, "BATCH11", test_raw_oplock_batch11);
3524 torture_suite_add_2smb_test(suite, "BATCH12", test_raw_oplock_batch12);
3525 torture_suite_add_2smb_test(suite, "BATCH13", test_raw_oplock_batch13);
3526 torture_suite_add_2smb_test(suite, "BATCH14", test_raw_oplock_batch14);
3527 torture_suite_add_2smb_test(suite, "BATCH15", test_raw_oplock_batch15);
3528 torture_suite_add_2smb_test(suite, "BATCH16", test_raw_oplock_batch16);
3529 torture_suite_add_2smb_test(suite, "BATCH17", test_raw_oplock_batch17);
3530 torture_suite_add_2smb_test(suite, "BATCH18", test_raw_oplock_batch18);
3531 torture_suite_add_2smb_test(suite, "BATCH19", test_raw_oplock_batch19);
3532 torture_suite_add_2smb_test(suite, "BATCH20", test_raw_oplock_batch20);
3533 torture_suite_add_2smb_test(suite, "BATCH21", test_raw_oplock_batch21);
3534 torture_suite_add_2smb_test(suite, "BATCH22", test_raw_oplock_batch22);
3535 torture_suite_add_2smb_test(suite, "BATCH23", test_raw_oplock_batch23);
3536 torture_suite_add_2smb_test(suite, "BATCH24", test_raw_oplock_batch24);
3537 torture_suite_add_2smb_test(suite, "BATCH25", test_raw_oplock_batch25);
3538 torture_suite_add_2smb_test(suite, "STREAM1", test_raw_oplock_stream1);
3539 torture_suite_add_1smb_test(suite, "DOC1", test_raw_oplock_doc);
3540 torture_suite_add_2smb_test(suite, "BRL1", test_raw_oplock_brl1);
3541 torture_suite_add_1smb_test(suite, "BRL2", test_raw_oplock_brl2);
3542 torture_suite_add_1smb_test(suite, "BRL3", test_raw_oplock_brl3);
3544 return suite;
3548 stress testing of oplocks
3550 bool torture_bench_oplock(struct torture_context *torture)
3552 struct smbcli_state **cli;
3553 bool ret = true;
3554 TALLOC_CTX *mem_ctx = talloc_new(torture);
3555 int torture_nprocs = torture_setting_int(torture, "nprocs", 4);
3556 int i, count=0;
3557 int timelimit = torture_setting_int(torture, "timelimit", 10);
3558 union smb_open io;
3559 struct timeval tv;
3561 cli = talloc_array(mem_ctx, struct smbcli_state *, torture_nprocs);
3563 torture_comment(torture, "Opening %d connections\n", torture_nprocs);
3564 for (i=0;i<torture_nprocs;i++) {
3565 if (!torture_open_connection_ev(&cli[i], i, torture, torture->ev)) {
3566 return false;
3568 talloc_steal(mem_ctx, cli[i]);
3569 smbcli_oplock_handler(cli[i]->transport, oplock_handler_close,
3570 cli[i]->tree);
3573 if (!torture_setup_dir(cli[0], BASEDIR)) {
3574 ret = false;
3575 goto done;
3578 io.ntcreatex.level = RAW_OPEN_NTCREATEX;
3579 io.ntcreatex.in.root_fid = 0;
3580 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3581 io.ntcreatex.in.alloc_size = 0;
3582 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3583 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3584 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3585 io.ntcreatex.in.create_options = 0;
3586 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3587 io.ntcreatex.in.security_flags = 0;
3588 io.ntcreatex.in.fname = BASEDIR "\\test.dat";
3589 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3590 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3591 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3593 tv = timeval_current();
3596 we open the same file with SHARE_ACCESS_NONE from all the
3597 connections in a round robin fashion. Each open causes an
3598 oplock break on the previous connection, which is answered
3599 by the oplock_handler_close() to close the file.
3601 This measures how fast we can pass on oplocks, and stresses
3602 the oplock handling code
3604 torture_comment(torture, "Running for %d seconds\n", timelimit);
3605 while (timeval_elapsed(&tv) < timelimit) {
3606 for (i=0;i<torture_nprocs;i++) {
3607 NTSTATUS status;
3609 status = smb_raw_open(cli[i]->tree, mem_ctx, &io);
3610 CHECK_STATUS(torture, status, NT_STATUS_OK);
3611 count++;
3614 if (torture_setting_bool(torture, "progress", true)) {
3615 torture_comment(torture, "%.2f ops/second\r", count/timeval_elapsed(&tv));
3619 torture_comment(torture, "%.2f ops/second\n", count/timeval_elapsed(&tv));
3621 smb_raw_exit(cli[torture_nprocs-1]->session);
3623 done:
3624 smb_raw_exit(cli[0]->session);
3625 smbcli_deltree(cli[0]->tree, BASEDIR);
3626 talloc_free(mem_ctx);
3627 return ret;
3631 static struct hold_oplock_info {
3632 const char *fname;
3633 bool close_on_break;
3634 uint32_t share_access;
3635 uint16_t fnum;
3636 } hold_info[] = {
3637 { BASEDIR "\\notshared_close", true,
3638 NTCREATEX_SHARE_ACCESS_NONE, },
3639 { BASEDIR "\\notshared_noclose", false,
3640 NTCREATEX_SHARE_ACCESS_NONE, },
3641 { BASEDIR "\\shared_close", true,
3642 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
3643 { BASEDIR "\\shared_noclose", false,
3644 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
3647 static bool oplock_handler_hold(struct smbcli_transport *transport,
3648 uint16_t tid, uint16_t fnum, uint8_t level,
3649 void *private_data)
3651 struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
3652 struct hold_oplock_info *info;
3653 int i;
3655 for (i=0;i<ARRAY_SIZE(hold_info);i++) {
3656 if (hold_info[i].fnum == fnum) break;
3659 if (i == ARRAY_SIZE(hold_info)) {
3660 printf("oplock break for unknown fnum %u\n", fnum);
3661 return false;
3664 info = &hold_info[i];
3666 if (info->close_on_break) {
3667 printf("oplock break on %s - closing\n",
3668 info->fname);
3669 oplock_handler_close(transport, tid, fnum, level, private_data);
3670 return true;
3673 printf("oplock break on %s - acking break\n", info->fname);
3675 return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
3680 used for manual testing of oplocks - especially interaction with
3681 other filesystems (such as NFS and local access)
3683 bool torture_hold_oplock(struct torture_context *torture,
3684 struct smbcli_state *cli)
3686 struct tevent_context *ev =
3687 (struct tevent_context *)cli->transport->socket->event.ctx;
3688 int i;
3690 printf("Setting up open files with oplocks in %s\n", BASEDIR);
3692 if (!torture_setup_dir(cli, BASEDIR)) {
3693 return false;
3696 smbcli_oplock_handler(cli->transport, oplock_handler_hold, cli->tree);
3698 /* setup the files */
3699 for (i=0;i<ARRAY_SIZE(hold_info);i++) {
3700 union smb_open io;
3701 NTSTATUS status;
3702 char c = 1;
3704 io.generic.level = RAW_OPEN_NTCREATEX;
3705 io.ntcreatex.in.root_fid = 0;
3706 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3707 io.ntcreatex.in.alloc_size = 0;
3708 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3709 io.ntcreatex.in.share_access = hold_info[i].share_access;
3710 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3711 io.ntcreatex.in.create_options = 0;
3712 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3713 io.ntcreatex.in.security_flags = 0;
3714 io.ntcreatex.in.fname = hold_info[i].fname;
3715 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3716 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3717 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3718 printf("opening %s\n", hold_info[i].fname);
3720 status = smb_raw_open(cli->tree, cli, &io);
3721 if (!NT_STATUS_IS_OK(status)) {
3722 printf("Failed to open %s - %s\n",
3723 hold_info[i].fname, nt_errstr(status));
3724 return false;
3727 if (io.ntcreatex.out.oplock_level != BATCH_OPLOCK_RETURN) {
3728 printf("Oplock not granted for %s - expected %d but got %d\n",
3729 hold_info[i].fname, BATCH_OPLOCK_RETURN,
3730 io.ntcreatex.out.oplock_level);
3731 return false;
3733 hold_info[i].fnum = io.ntcreatex.out.file.fnum;
3735 /* make the file non-zero size */
3736 if (smbcli_write(cli->tree, hold_info[i].fnum, 0, &c, 0, 1) != 1) {
3737 printf("Failed to write to file\n");
3738 return false;
3742 printf("Waiting for oplock events\n");
3743 event_loop_wait(ev);
3745 return true;