Fix a bunch of "warning: variable ‘XXXX’ set but not used [-Wunused-but-set-variable...
[Samba/gebeck_regimport.git] / source4 / torture / raw / oplock.c
blobd3c7aae0250fea5af7b03e42bca7e9811ff3e1cf
1 /*
2 Unix SMB/CIFS implementation.
3 basic raw test suite for oplocks
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "libcli/raw/libcliraw.h"
22 #include "libcli/raw/raw_proto.h"
23 #include "libcli/libcli.h"
24 #include "torture/util.h"
25 #include "lib/events/events.h"
26 #include "param/param.h"
27 #include "lib/cmdline/popt_common.h"
28 #include "libcli/resolve/resolve.h"
29 #include "torture/raw/proto.h"
31 #define CHECK_VAL(v, correct) do { \
32 if ((v) != (correct)) { \
33 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
34 __location__, #v, (int)v, (int)correct); \
35 ret = false; \
36 }} while (0)
38 #define CHECK_RANGE(v, min, max) do { \
39 if ((v) < (min) || (v) > (max)) { \
40 torture_warning(tctx, "(%s): wrong value for %s got " \
41 "%d - should be between %d and %d\n", \
42 __location__, #v, (int)v, (int)min, (int)max); \
43 }} while (0)
45 #define CHECK_STRMATCH(v, correct) do { \
46 if (!v || strstr((v),(correct)) == NULL) { \
47 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got '%s' - should be '%s'\n", \
48 __location__, #v, v?v:"NULL", correct); \
49 ret = false; \
50 } \
51 } while (0)
53 #define CHECK_STATUS(tctx, status, correct) do { \
54 if (!NT_STATUS_EQUAL(status, correct)) { \
55 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
56 nt_errstr(status), nt_errstr(correct)); \
57 ret = false; \
58 goto done; \
59 }} while (0)
62 static struct {
63 int fnum;
64 uint8_t level;
65 int count;
66 int failures;
67 } break_info;
69 #define BASEDIR "\\test_oplock"
72 a handler function for oplock break requests. Ack it as a break to level II if possible
74 static bool oplock_handler_ack_to_given(struct smbcli_transport *transport,
75 uint16_t tid, uint16_t fnum,
76 uint8_t level, void *private_data)
78 struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
79 const char *name;
81 break_info.fnum = fnum;
82 break_info.level = level;
83 break_info.count++;
85 switch (level) {
86 case OPLOCK_BREAK_TO_LEVEL_II:
87 name = "level II";
88 break;
89 case OPLOCK_BREAK_TO_NONE:
90 name = "none";
91 break;
92 default:
93 name = "unknown";
94 break_info.failures++;
96 printf("Acking to %s [0x%02X] in oplock handler\n",
97 name, level);
99 return smbcli_oplock_ack(tree, fnum, level);
103 a handler function for oplock break requests. Ack it as a break to none
105 static bool oplock_handler_ack_to_none(struct smbcli_transport *transport,
106 uint16_t tid, uint16_t fnum,
107 uint8_t level, void *private_data)
109 struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
110 break_info.fnum = fnum;
111 break_info.level = level;
112 break_info.count++;
114 printf("Acking to none in oplock handler\n");
116 return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
120 a handler function for oplock break requests. Let it timeout
122 static bool oplock_handler_timeout(struct smbcli_transport *transport,
123 uint16_t tid, uint16_t fnum,
124 uint8_t level, void *private_data)
126 break_info.fnum = fnum;
127 break_info.level = level;
128 break_info.count++;
130 printf("Let oplock break timeout\n");
131 return true;
134 static void oplock_handler_close_recv(struct smbcli_request *req)
136 NTSTATUS status;
137 status = smbcli_request_simple_recv(req);
138 if (!NT_STATUS_IS_OK(status)) {
139 printf("close failed in oplock_handler_close\n");
140 break_info.failures++;
145 a handler function for oplock break requests - close the file
147 static bool oplock_handler_close(struct smbcli_transport *transport, uint16_t tid,
148 uint16_t fnum, uint8_t level, void *private_data)
150 union smb_close io;
151 struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
152 struct smbcli_request *req;
154 break_info.fnum = fnum;
155 break_info.level = level;
156 break_info.count++;
158 io.close.level = RAW_CLOSE_CLOSE;
159 io.close.in.file.fnum = fnum;
160 io.close.in.write_time = 0;
161 req = smb_raw_close_send(tree, &io);
162 if (req == NULL) {
163 printf("failed to send close in oplock_handler_close\n");
164 return false;
167 req->async.fn = oplock_handler_close_recv;
168 req->async.private_data = NULL;
170 return true;
173 static bool open_connection_no_level2_oplocks(struct torture_context *tctx,
174 struct smbcli_state **c)
176 NTSTATUS status;
177 struct smbcli_options options;
178 struct smbcli_session_options session_options;
180 lpcfg_smbcli_options(tctx->lp_ctx, &options);
181 lpcfg_smbcli_session_options(tctx->lp_ctx, &session_options);
183 options.use_level2_oplocks = false;
185 status = smbcli_full_connection(tctx, c,
186 torture_setting_string(tctx, "host", NULL),
187 lpcfg_smb_ports(tctx->lp_ctx),
188 torture_setting_string(tctx, "share", NULL),
189 NULL, lpcfg_socket_options(tctx->lp_ctx), cmdline_credentials,
190 lpcfg_resolve_context(tctx->lp_ctx),
191 tctx->ev, &options, &session_options,
192 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
193 if (!NT_STATUS_IS_OK(status)) {
194 torture_comment(tctx, "Failed to open connection - %s\n",
195 nt_errstr(status));
196 return false;
199 return true;
203 Timer handler function notifies the registering function that time is up
205 static void timeout_cb(struct tevent_context *ev,
206 struct tevent_timer *te,
207 struct timeval current_time,
208 void *private_data)
210 bool *timesup = (bool *)private_data;
211 *timesup = true;
212 return;
216 Wait a short period of time to receive a single oplock break request
218 static void torture_wait_for_oplock_break(struct torture_context *tctx)
220 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
221 struct tevent_timer *te = NULL;
222 struct timeval ne;
223 bool timesup = false;
224 int old_count = break_info.count;
226 /* Wait .1 seconds for an oplock break */
227 ne = tevent_timeval_current_ofs(0, 100000);
229 if ((te = tevent_add_timer(tctx->ev, tmp_ctx, ne, timeout_cb, &timesup))
230 == NULL)
232 torture_comment(tctx, "Failed to wait for an oplock break. "
233 "test results may not be accurate.");
234 goto done;
237 while (!timesup && break_info.count < old_count + 1) {
238 if (tevent_loop_once(tctx->ev) != 0) {
239 torture_comment(tctx, "Failed to wait for an oplock "
240 "break. test results may not be "
241 "accurate.");
242 goto done;
246 done:
247 /* We don't know if the timed event fired and was freed, we received
248 * our oplock break, or some other event triggered the loop. Thus,
249 * we create a tmp_ctx to be able to safely free/remove the timed
250 * event in all 3 cases. */
251 talloc_free(tmp_ctx);
253 return;
256 static uint8_t get_break_level1_to_none_count(struct torture_context *tctx)
258 return torture_setting_bool(tctx, "2_step_break_to_none", false) ?
259 2 : 1;
262 static bool test_raw_oplock_exclusive1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
264 const char *fname = BASEDIR "\\test_exclusive1.dat";
265 NTSTATUS status;
266 bool ret = true;
267 union smb_open io;
268 union smb_unlink unl;
269 uint16_t fnum=0;
271 if (!torture_setup_dir(cli1, BASEDIR)) {
272 return false;
275 /* cleanup */
276 smbcli_unlink(cli1->tree, fname);
278 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
281 base ntcreatex parms
283 io.generic.level = RAW_OPEN_NTCREATEX;
284 io.ntcreatex.in.root_fid.fnum = 0;
285 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
286 io.ntcreatex.in.alloc_size = 0;
287 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
288 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
289 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
290 io.ntcreatex.in.create_options = 0;
291 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
292 io.ntcreatex.in.security_flags = 0;
293 io.ntcreatex.in.fname = fname;
295 torture_comment(tctx, "EXCLUSIVE1: open a file with an exclusive oplock (share mode: none)\n");
296 ZERO_STRUCT(break_info);
297 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
299 status = smb_raw_open(cli1->tree, tctx, &io);
300 CHECK_STATUS(tctx, status, NT_STATUS_OK);
301 fnum = io.ntcreatex.out.file.fnum;
302 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
304 torture_comment(tctx, "a 2nd open should not cause a break\n");
305 status = smb_raw_open(cli2->tree, tctx, &io);
306 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
307 torture_wait_for_oplock_break(tctx);
308 CHECK_VAL(break_info.count, 0);
309 CHECK_VAL(break_info.failures, 0);
311 torture_comment(tctx, "unlink it - should also be no break\n");
312 unl.unlink.in.pattern = fname;
313 unl.unlink.in.attrib = 0;
314 status = smb_raw_unlink(cli2->tree, &unl);
315 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
316 torture_wait_for_oplock_break(tctx);
317 CHECK_VAL(break_info.count, 0);
318 CHECK_VAL(break_info.failures, 0);
320 smbcli_close(cli1->tree, fnum);
322 done:
323 smb_raw_exit(cli1->session);
324 smb_raw_exit(cli2->session);
325 smbcli_deltree(cli1->tree, BASEDIR);
326 return ret;
329 static bool test_raw_oplock_exclusive2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
331 const char *fname = BASEDIR "\\test_exclusive2.dat";
332 NTSTATUS status;
333 bool ret = true;
334 union smb_open io;
335 union smb_unlink unl;
336 uint16_t fnum=0, fnum2=0;
338 if (!torture_setup_dir(cli1, BASEDIR)) {
339 return false;
342 /* cleanup */
343 smbcli_unlink(cli1->tree, fname);
345 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
348 base ntcreatex parms
350 io.generic.level = RAW_OPEN_NTCREATEX;
351 io.ntcreatex.in.root_fid.fnum = 0;
352 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
353 io.ntcreatex.in.alloc_size = 0;
354 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
355 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
356 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
357 io.ntcreatex.in.create_options = 0;
358 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
359 io.ntcreatex.in.security_flags = 0;
360 io.ntcreatex.in.fname = fname;
362 torture_comment(tctx, "EXCLUSIVE2: open a file with an exclusive oplock (share mode: all)\n");
363 ZERO_STRUCT(break_info);
364 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
365 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
366 NTCREATEX_SHARE_ACCESS_WRITE|
367 NTCREATEX_SHARE_ACCESS_DELETE;
369 status = smb_raw_open(cli1->tree, tctx, &io);
370 CHECK_STATUS(tctx, status, NT_STATUS_OK);
371 fnum = io.ntcreatex.out.file.fnum;
372 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
374 torture_comment(tctx, "a 2nd open should cause a break to level 2\n");
375 status = smb_raw_open(cli2->tree, tctx, &io);
376 CHECK_STATUS(tctx, status, NT_STATUS_OK);
377 fnum2 = io.ntcreatex.out.file.fnum;
378 torture_wait_for_oplock_break(tctx);
379 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
380 CHECK_VAL(break_info.count, 1);
381 CHECK_VAL(break_info.fnum, fnum);
382 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
383 CHECK_VAL(break_info.failures, 0);
384 ZERO_STRUCT(break_info);
386 /* now we have 2 level II oplocks... */
387 torture_comment(tctx, "try to unlink it - should not cause a break, but a sharing violation\n");
388 unl.unlink.in.pattern = fname;
389 unl.unlink.in.attrib = 0;
390 status = smb_raw_unlink(cli2->tree, &unl);
391 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
392 torture_wait_for_oplock_break(tctx);
393 CHECK_VAL(break_info.count, 0);
394 CHECK_VAL(break_info.failures, 0);
396 torture_comment(tctx, "close 1st handle\n");
397 smbcli_close(cli1->tree, fnum);
399 torture_comment(tctx, "try to unlink it - should not cause a break, but a sharing violation\n");
400 unl.unlink.in.pattern = fname;
401 unl.unlink.in.attrib = 0;
402 status = smb_raw_unlink(cli2->tree, &unl);
403 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
404 torture_wait_for_oplock_break(tctx);
405 CHECK_VAL(break_info.count, 0);
406 CHECK_VAL(break_info.failures, 0);
408 torture_comment(tctx, "close 2nd handle\n");
409 smbcli_close(cli2->tree, fnum2);
411 torture_comment(tctx, "unlink it\n");
412 unl.unlink.in.pattern = fname;
413 unl.unlink.in.attrib = 0;
414 status = smb_raw_unlink(cli2->tree, &unl);
415 CHECK_STATUS(tctx, status, NT_STATUS_OK);
416 torture_wait_for_oplock_break(tctx);
417 CHECK_VAL(break_info.count, 0);
418 CHECK_VAL(break_info.failures, 0);
420 done:
421 smb_raw_exit(cli1->session);
422 smb_raw_exit(cli2->session);
423 smbcli_deltree(cli1->tree, BASEDIR);
424 return ret;
427 static bool test_raw_oplock_exclusive3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
429 const char *fname = BASEDIR "\\test_exclusive3.dat";
430 NTSTATUS status;
431 bool ret = true;
432 union smb_open io;
433 union smb_setfileinfo sfi;
434 uint16_t fnum=0;
436 if (!torture_setup_dir(cli1, BASEDIR)) {
437 return false;
440 /* cleanup */
441 smbcli_unlink(cli1->tree, fname);
443 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
446 base ntcreatex parms
448 io.generic.level = RAW_OPEN_NTCREATEX;
449 io.ntcreatex.in.root_fid.fnum = 0;
450 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
451 io.ntcreatex.in.alloc_size = 0;
452 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
453 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE;
454 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
455 io.ntcreatex.in.create_options = 0;
456 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
457 io.ntcreatex.in.security_flags = 0;
458 io.ntcreatex.in.fname = fname;
460 torture_comment(tctx, "EXCLUSIVE3: open a file with an exclusive oplock (share mode: none)\n");
462 ZERO_STRUCT(break_info);
463 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
465 status = smb_raw_open(cli1->tree, tctx, &io);
466 CHECK_STATUS(tctx, status, NT_STATUS_OK);
467 fnum = io.ntcreatex.out.file.fnum;
468 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
470 torture_comment(tctx, "setpathinfo EOF should trigger a break to none\n");
471 ZERO_STRUCT(sfi);
472 sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
473 sfi.generic.in.file.path = fname;
474 sfi.end_of_file_info.in.size = 100;
476 status = smb_raw_setpathinfo(cli2->tree, &sfi);
478 CHECK_STATUS(tctx, status, NT_STATUS_OK);
479 torture_wait_for_oplock_break(tctx);
480 CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
481 CHECK_VAL(break_info.failures, 0);
482 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
484 smbcli_close(cli1->tree, fnum);
486 done:
487 smb_raw_exit(cli1->session);
488 smb_raw_exit(cli2->session);
489 smbcli_deltree(cli1->tree, BASEDIR);
490 return ret;
493 static bool test_raw_oplock_exclusive4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
495 const char *fname = BASEDIR "\\test_exclusive4.dat";
496 NTSTATUS status;
497 bool ret = true;
498 union smb_open io;
499 uint16_t fnum=0, fnum2=0;
501 if (!torture_setup_dir(cli1, BASEDIR)) {
502 return false;
505 /* cleanup */
506 smbcli_unlink(cli1->tree, fname);
508 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
511 base ntcreatex parms
513 io.generic.level = RAW_OPEN_NTCREATEX;
514 io.ntcreatex.in.root_fid.fnum = 0;
515 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
516 io.ntcreatex.in.alloc_size = 0;
517 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
518 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
519 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
520 io.ntcreatex.in.create_options = 0;
521 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
522 io.ntcreatex.in.security_flags = 0;
523 io.ntcreatex.in.fname = fname;
525 torture_comment(tctx, "EXCLUSIVE4: open with exclusive oplock\n");
526 ZERO_STRUCT(break_info);
527 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
529 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
530 status = smb_raw_open(cli1->tree, tctx, &io);
531 CHECK_STATUS(tctx, status, NT_STATUS_OK);
532 fnum = io.ntcreatex.out.file.fnum;
533 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
535 ZERO_STRUCT(break_info);
536 torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
538 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
539 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
540 status = smb_raw_open(cli2->tree, tctx, &io);
541 CHECK_STATUS(tctx, status, NT_STATUS_OK);
542 fnum2 = io.ntcreatex.out.file.fnum;
543 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
544 torture_wait_for_oplock_break(tctx);
545 CHECK_VAL(break_info.count, 0);
546 CHECK_VAL(break_info.failures, 0);
548 smbcli_close(cli1->tree, fnum);
549 smbcli_close(cli2->tree, fnum2);
551 done:
552 smb_raw_exit(cli1->session);
553 smb_raw_exit(cli2->session);
554 smbcli_deltree(cli1->tree, BASEDIR);
555 return ret;
558 static bool test_raw_oplock_exclusive5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
560 const char *fname = BASEDIR "\\test_exclusive5.dat";
561 NTSTATUS status;
562 bool ret = true;
563 union smb_open io;
564 uint16_t fnum=0, fnum2=0;
566 if (!torture_setup_dir(cli1, BASEDIR)) {
567 return false;
570 /* cleanup */
571 smbcli_unlink(cli1->tree, fname);
573 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
574 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
577 base ntcreatex parms
579 io.generic.level = RAW_OPEN_NTCREATEX;
580 io.ntcreatex.in.root_fid.fnum = 0;
581 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
582 io.ntcreatex.in.alloc_size = 0;
583 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
584 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
585 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
586 io.ntcreatex.in.create_options = 0;
587 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
588 io.ntcreatex.in.security_flags = 0;
589 io.ntcreatex.in.fname = fname;
591 torture_comment(tctx, "EXCLUSIVE5: open with exclusive oplock\n");
592 ZERO_STRUCT(break_info);
593 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
596 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
597 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
598 NTCREATEX_SHARE_ACCESS_WRITE|
599 NTCREATEX_SHARE_ACCESS_DELETE;
600 status = smb_raw_open(cli1->tree, tctx, &io);
601 CHECK_STATUS(tctx, status, NT_STATUS_OK);
602 fnum = io.ntcreatex.out.file.fnum;
603 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
605 ZERO_STRUCT(break_info);
607 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
609 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
610 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
611 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
612 status = smb_raw_open(cli2->tree, tctx, &io);
613 CHECK_STATUS(tctx, status, NT_STATUS_OK);
614 fnum2 = io.ntcreatex.out.file.fnum;
615 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
616 torture_wait_for_oplock_break(tctx);
617 CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
618 CHECK_VAL(break_info.failures, 0);
620 smbcli_close(cli1->tree, fnum);
621 smbcli_close(cli2->tree, fnum2);
623 done:
624 smb_raw_exit(cli1->session);
625 smb_raw_exit(cli2->session);
626 smbcli_deltree(cli1->tree, BASEDIR);
627 return ret;
630 static bool test_raw_oplock_exclusive6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
632 const char *fname1 = BASEDIR "\\test_exclusive6_1.dat";
633 const char *fname2 = BASEDIR "\\test_exclusive6_2.dat";
634 NTSTATUS status;
635 bool ret = true;
636 union smb_open io;
637 union smb_rename rn;
638 uint16_t fnum=0;
640 if (!torture_setup_dir(cli1, BASEDIR)) {
641 return false;
644 /* cleanup */
645 smbcli_unlink(cli1->tree, fname1);
646 smbcli_unlink(cli1->tree, fname2);
648 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
651 base ntcreatex parms
653 io.generic.level = RAW_OPEN_NTCREATEX;
654 io.ntcreatex.in.root_fid.fnum = 0;
655 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
656 io.ntcreatex.in.alloc_size = 0;
657 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
658 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
659 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
660 io.ntcreatex.in.create_options = 0;
661 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
662 io.ntcreatex.in.security_flags = 0;
663 io.ntcreatex.in.fname = fname1;
665 torture_comment(tctx, "EXCLUSIVE6: open a file with an exclusive "
666 "oplock (share mode: none)\n");
667 ZERO_STRUCT(break_info);
668 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
670 status = smb_raw_open(cli1->tree, tctx, &io);
671 CHECK_STATUS(tctx, status, NT_STATUS_OK);
672 fnum = io.ntcreatex.out.file.fnum;
673 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
675 torture_comment(tctx, "rename should not generate a break but get a "
676 "sharing violation\n");
677 ZERO_STRUCT(rn);
678 rn.generic.level = RAW_RENAME_RENAME;
679 rn.rename.in.pattern1 = fname1;
680 rn.rename.in.pattern2 = fname2;
681 rn.rename.in.attrib = 0;
683 torture_comment(tctx, "trying rename while first file open\n");
684 status = smb_raw_rename(cli2->tree, &rn);
686 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
687 torture_wait_for_oplock_break(tctx);
688 CHECK_VAL(break_info.count, 0);
689 CHECK_VAL(break_info.failures, 0);
691 smbcli_close(cli1->tree, fnum);
693 done:
694 smb_raw_exit(cli1->session);
695 smb_raw_exit(cli2->session);
696 smbcli_deltree(cli1->tree, BASEDIR);
697 return ret;
701 * Exclusive version of batch19
703 static bool test_raw_oplock_exclusive7(struct torture_context *tctx,
704 struct smbcli_state *cli1, struct smbcli_state *cli2)
706 const char *fname1 = BASEDIR "\\test_exclusiv6_1.dat";
707 const char *fname2 = BASEDIR "\\test_exclusiv6_2.dat";
708 const char *fname3 = BASEDIR "\\test_exclusiv6_3.dat";
709 NTSTATUS status;
710 bool ret = true;
711 union smb_open io;
712 union smb_fileinfo qfi;
713 union smb_setfileinfo sfi;
714 uint16_t fnum=0;
715 uint16_t fnum2 = 0;
717 if (!torture_setup_dir(cli1, BASEDIR)) {
718 return false;
721 /* cleanup */
722 smbcli_unlink(cli1->tree, fname1);
723 smbcli_unlink(cli1->tree, fname2);
724 smbcli_unlink(cli1->tree, fname3);
726 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
727 cli1->tree);
730 base ntcreatex parms
732 io.generic.level = RAW_OPEN_NTCREATEX;
733 io.ntcreatex.in.root_fid.fnum = 0;
734 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
735 io.ntcreatex.in.alloc_size = 0;
736 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
737 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
738 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
739 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
740 io.ntcreatex.in.create_options = 0;
741 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
742 io.ntcreatex.in.security_flags = 0;
743 io.ntcreatex.in.fname = fname1;
745 torture_comment(tctx, "open a file with an exclusive oplock (share "
746 "mode: none)\n");
747 ZERO_STRUCT(break_info);
748 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
749 NTCREATEX_FLAGS_REQUEST_OPLOCK;
750 status = smb_raw_open(cli1->tree, tctx, &io);
751 CHECK_STATUS(tctx, status, NT_STATUS_OK);
752 fnum = io.ntcreatex.out.file.fnum;
753 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
755 torture_comment(tctx, "setpathinfo rename info should trigger a break "
756 "to none\n");
757 ZERO_STRUCT(sfi);
758 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
759 sfi.generic.in.file.path = fname1;
760 sfi.rename_information.in.overwrite = 0;
761 sfi.rename_information.in.root_fid = 0;
762 sfi.rename_information.in.new_name = fname2+strlen(BASEDIR)+1;
764 status = smb_raw_setpathinfo(cli2->tree, &sfi);
765 CHECK_STATUS(tctx, status, NT_STATUS_OK);
767 torture_wait_for_oplock_break(tctx);
768 CHECK_VAL(break_info.failures, 0);
770 if (TARGET_IS_WINXP(tctx)) {
771 /* XP incorrectly breaks to level2. */
772 CHECK_VAL(break_info.count, 1);
773 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
774 } else {
775 /* Exclusive oplocks should not be broken on rename. */
776 CHECK_VAL(break_info.failures, 0);
777 CHECK_VAL(break_info.count, 0);
780 ZERO_STRUCT(qfi);
781 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
782 qfi.generic.in.file.fnum = fnum;
784 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
785 CHECK_STATUS(tctx, status, NT_STATUS_OK);
786 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
788 /* Try breaking to level2 and then see if rename breaks the level2.*/
789 ZERO_STRUCT(break_info);
790 io.ntcreatex.in.fname = fname2;
791 status = smb_raw_open(cli2->tree, tctx, &io);
792 CHECK_STATUS(tctx, status, NT_STATUS_OK);
793 fnum2 = io.ntcreatex.out.file.fnum;
794 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
796 torture_wait_for_oplock_break(tctx);
797 CHECK_VAL(break_info.failures, 0);
799 if (TARGET_IS_WINXP(tctx)) {
800 /* XP already broke to level2. */
801 CHECK_VAL(break_info.failures, 0);
802 CHECK_VAL(break_info.count, 0);
803 } else {
804 /* Break to level 2 expected. */
805 CHECK_VAL(break_info.count, 1);
806 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
809 ZERO_STRUCT(break_info);
810 sfi.generic.in.file.path = fname2;
811 sfi.rename_information.in.overwrite = 0;
812 sfi.rename_information.in.root_fid = 0;
813 sfi.rename_information.in.new_name = fname1+strlen(BASEDIR)+1;
815 status = smb_raw_setpathinfo(cli2->tree, &sfi);
816 CHECK_STATUS(tctx, status, NT_STATUS_OK);
818 /* Level2 oplocks are not broken on rename. */
819 torture_wait_for_oplock_break(tctx);
820 CHECK_VAL(break_info.failures, 0);
821 CHECK_VAL(break_info.count, 0);
823 /* Close and re-open file with oplock. */
824 smbcli_close(cli1->tree, fnum);
825 status = smb_raw_open(cli1->tree, tctx, &io);
826 CHECK_STATUS(tctx, status, NT_STATUS_OK);
827 fnum = io.ntcreatex.out.file.fnum;
828 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
830 torture_comment(tctx, "setfileinfo rename info on a client's own fid "
831 "should not trigger a break nor a violation\n");
832 ZERO_STRUCT(break_info);
833 ZERO_STRUCT(sfi);
834 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
835 sfi.generic.in.file.fnum = fnum;
836 sfi.rename_information.in.overwrite = 0;
837 sfi.rename_information.in.root_fid = 0;
838 sfi.rename_information.in.new_name = fname3+strlen(BASEDIR)+1;
840 status = smb_raw_setfileinfo(cli1->tree, &sfi);
841 CHECK_STATUS(tctx, status, NT_STATUS_OK);
843 torture_wait_for_oplock_break(tctx);
844 if (TARGET_IS_WINXP(tctx)) {
845 /* XP incorrectly breaks to level2. */
846 CHECK_VAL(break_info.count, 1);
847 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
848 } else {
849 CHECK_VAL(break_info.count, 0);
852 ZERO_STRUCT(qfi);
853 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
854 qfi.generic.in.file.fnum = fnum;
856 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
857 CHECK_STATUS(tctx, status, NT_STATUS_OK);
858 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
860 done:
861 smbcli_close(cli1->tree, fnum);
862 smbcli_close(cli2->tree, fnum2);
864 smb_raw_exit(cli1->session);
865 smb_raw_exit(cli2->session);
866 smbcli_deltree(cli1->tree, BASEDIR);
867 return ret;
870 static bool test_raw_oplock_batch1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
872 const char *fname = BASEDIR "\\test_batch1.dat";
873 NTSTATUS status;
874 bool ret = true;
875 union smb_open io;
876 union smb_unlink unl;
877 uint16_t fnum=0;
878 char c = 0;
880 if (!torture_setup_dir(cli1, BASEDIR)) {
881 return false;
884 /* cleanup */
885 smbcli_unlink(cli1->tree, fname);
887 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
890 base ntcreatex parms
892 io.generic.level = RAW_OPEN_NTCREATEX;
893 io.ntcreatex.in.root_fid.fnum = 0;
894 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
895 io.ntcreatex.in.alloc_size = 0;
896 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
897 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
898 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
899 io.ntcreatex.in.create_options = 0;
900 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
901 io.ntcreatex.in.security_flags = 0;
902 io.ntcreatex.in.fname = fname;
905 with a batch oplock we get a break
907 torture_comment(tctx, "BATCH1: open with batch oplock\n");
908 ZERO_STRUCT(break_info);
909 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
910 NTCREATEX_FLAGS_REQUEST_OPLOCK |
911 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
912 status = smb_raw_open(cli1->tree, tctx, &io);
913 CHECK_STATUS(tctx, status, NT_STATUS_OK);
914 fnum = io.ntcreatex.out.file.fnum;
915 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
917 torture_comment(tctx, "unlink should generate a break\n");
918 unl.unlink.in.pattern = fname;
919 unl.unlink.in.attrib = 0;
920 status = smb_raw_unlink(cli2->tree, &unl);
921 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
923 torture_wait_for_oplock_break(tctx);
924 CHECK_VAL(break_info.count, 1);
925 CHECK_VAL(break_info.fnum, fnum);
926 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
927 CHECK_VAL(break_info.failures, 0);
929 torture_comment(tctx, "2nd unlink should not generate a break\n");
930 ZERO_STRUCT(break_info);
931 status = smb_raw_unlink(cli2->tree, &unl);
932 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
934 torture_wait_for_oplock_break(tctx);
935 CHECK_VAL(break_info.count, 0);
937 torture_comment(tctx, "writing should generate a self break to none\n");
938 smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
940 torture_wait_for_oplock_break(tctx);
941 torture_wait_for_oplock_break(tctx);
942 CHECK_VAL(break_info.count, 1);
943 CHECK_VAL(break_info.fnum, fnum);
944 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
945 CHECK_VAL(break_info.failures, 0);
947 smbcli_close(cli1->tree, fnum);
949 done:
950 smb_raw_exit(cli1->session);
951 smb_raw_exit(cli2->session);
952 smbcli_deltree(cli1->tree, BASEDIR);
953 return ret;
956 static bool test_raw_oplock_batch2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
958 const char *fname = BASEDIR "\\test_batch2.dat";
959 NTSTATUS status;
960 bool ret = true;
961 union smb_open io;
962 union smb_unlink unl;
963 uint16_t fnum=0;
964 char c = 0;
966 if (!torture_setup_dir(cli1, BASEDIR)) {
967 return false;
970 /* cleanup */
971 smbcli_unlink(cli1->tree, fname);
973 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
976 base ntcreatex parms
978 io.generic.level = RAW_OPEN_NTCREATEX;
979 io.ntcreatex.in.root_fid.fnum = 0;
980 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
981 io.ntcreatex.in.alloc_size = 0;
982 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
983 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
984 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
985 io.ntcreatex.in.create_options = 0;
986 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
987 io.ntcreatex.in.security_flags = 0;
988 io.ntcreatex.in.fname = fname;
990 torture_comment(tctx, "BATCH2: open with batch oplock\n");
991 ZERO_STRUCT(break_info);
992 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
993 NTCREATEX_FLAGS_REQUEST_OPLOCK |
994 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
995 status = smb_raw_open(cli1->tree, tctx, &io);
996 CHECK_STATUS(tctx, status, NT_STATUS_OK);
997 fnum = io.ntcreatex.out.file.fnum;
998 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1000 torture_comment(tctx, "unlink should generate a break, which we ack as break to none\n");
1001 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_none, cli1->tree);
1002 unl.unlink.in.pattern = fname;
1003 unl.unlink.in.attrib = 0;
1004 status = smb_raw_unlink(cli2->tree, &unl);
1005 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1007 torture_wait_for_oplock_break(tctx);
1008 CHECK_VAL(break_info.count, 1);
1009 CHECK_VAL(break_info.fnum, fnum);
1010 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1011 CHECK_VAL(break_info.failures, 0);
1013 torture_comment(tctx, "2nd unlink should not generate a break\n");
1014 ZERO_STRUCT(break_info);
1015 status = smb_raw_unlink(cli2->tree, &unl);
1016 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1018 torture_wait_for_oplock_break(tctx);
1019 CHECK_VAL(break_info.count, 0);
1021 torture_comment(tctx, "writing should not generate a break\n");
1022 smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
1024 torture_wait_for_oplock_break(tctx);
1025 CHECK_VAL(break_info.count, 0);
1027 smbcli_close(cli1->tree, fnum);
1029 done:
1030 smb_raw_exit(cli1->session);
1031 smb_raw_exit(cli2->session);
1032 smbcli_deltree(cli1->tree, BASEDIR);
1033 return ret;
1036 static bool test_raw_oplock_batch3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1038 const char *fname = BASEDIR "\\test_batch3.dat";
1039 NTSTATUS status;
1040 bool ret = true;
1041 union smb_open io;
1042 union smb_unlink unl;
1043 uint16_t fnum=0;
1045 if (!torture_setup_dir(cli1, BASEDIR)) {
1046 return false;
1049 /* cleanup */
1050 smbcli_unlink(cli1->tree, fname);
1052 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1055 base ntcreatex parms
1057 io.generic.level = RAW_OPEN_NTCREATEX;
1058 io.ntcreatex.in.root_fid.fnum = 0;
1059 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1060 io.ntcreatex.in.alloc_size = 0;
1061 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1062 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1063 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1064 io.ntcreatex.in.create_options = 0;
1065 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1066 io.ntcreatex.in.security_flags = 0;
1067 io.ntcreatex.in.fname = fname;
1069 torture_comment(tctx, "BATCH3: if we close on break then the unlink can succeed\n");
1070 ZERO_STRUCT(break_info);
1071 smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
1072 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1073 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1074 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1075 status = smb_raw_open(cli1->tree, tctx, &io);
1076 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1077 fnum = io.ntcreatex.out.file.fnum;
1078 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1080 unl.unlink.in.pattern = fname;
1081 unl.unlink.in.attrib = 0;
1082 ZERO_STRUCT(break_info);
1083 status = smb_raw_unlink(cli2->tree, &unl);
1084 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1086 torture_wait_for_oplock_break(tctx);
1087 CHECK_VAL(break_info.count, 1);
1088 CHECK_VAL(break_info.fnum, fnum);
1089 CHECK_VAL(break_info.level, 1);
1090 CHECK_VAL(break_info.failures, 0);
1092 smbcli_close(cli1->tree, fnum);
1094 done:
1095 smb_raw_exit(cli1->session);
1096 smb_raw_exit(cli2->session);
1097 smbcli_deltree(cli1->tree, BASEDIR);
1098 return ret;
1101 static bool test_raw_oplock_batch4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1103 const char *fname = BASEDIR "\\test_batch4.dat";
1104 NTSTATUS status;
1105 bool ret = true;
1106 union smb_open io;
1107 union smb_read rd;
1108 uint16_t fnum=0;
1110 if (!torture_setup_dir(cli1, BASEDIR)) {
1111 return false;
1114 /* cleanup */
1115 smbcli_unlink(cli1->tree, fname);
1117 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1120 base ntcreatex parms
1122 io.generic.level = RAW_OPEN_NTCREATEX;
1123 io.ntcreatex.in.root_fid.fnum = 0;
1124 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1125 io.ntcreatex.in.alloc_size = 0;
1126 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1127 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1128 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1129 io.ntcreatex.in.create_options = 0;
1130 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1131 io.ntcreatex.in.security_flags = 0;
1132 io.ntcreatex.in.fname = fname;
1134 torture_comment(tctx, "BATCH4: a self read should not cause a break\n");
1135 ZERO_STRUCT(break_info);
1136 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1138 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1139 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1140 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1141 status = smb_raw_open(cli1->tree, tctx, &io);
1142 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1143 fnum = io.ntcreatex.out.file.fnum;
1144 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1146 rd.readx.level = RAW_READ_READX;
1147 rd.readx.in.file.fnum = fnum;
1148 rd.readx.in.mincnt = 1;
1149 rd.readx.in.maxcnt = 1;
1150 rd.readx.in.offset = 0;
1151 rd.readx.in.remaining = 0;
1152 rd.readx.in.read_for_execute = false;
1153 status = smb_raw_read(cli1->tree, &rd);
1154 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1155 torture_wait_for_oplock_break(tctx);
1156 CHECK_VAL(break_info.count, 0);
1157 CHECK_VAL(break_info.failures, 0);
1159 smbcli_close(cli1->tree, fnum);
1161 done:
1162 smb_raw_exit(cli1->session);
1163 smb_raw_exit(cli2->session);
1164 smbcli_deltree(cli1->tree, BASEDIR);
1165 return ret;
1168 static bool test_raw_oplock_batch5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1170 const char *fname = BASEDIR "\\test_batch5.dat";
1171 NTSTATUS status;
1172 bool ret = true;
1173 union smb_open io;
1174 uint16_t fnum=0;
1176 if (!torture_setup_dir(cli1, BASEDIR)) {
1177 return false;
1180 /* cleanup */
1181 smbcli_unlink(cli1->tree, fname);
1183 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1186 base ntcreatex parms
1188 io.generic.level = RAW_OPEN_NTCREATEX;
1189 io.ntcreatex.in.root_fid.fnum = 0;
1190 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1191 io.ntcreatex.in.alloc_size = 0;
1192 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1193 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1194 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1195 io.ntcreatex.in.create_options = 0;
1196 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1197 io.ntcreatex.in.security_flags = 0;
1198 io.ntcreatex.in.fname = fname;
1200 torture_comment(tctx, "BATCH5: a 2nd open should give a break\n");
1201 ZERO_STRUCT(break_info);
1202 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1204 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1205 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1206 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1207 status = smb_raw_open(cli1->tree, tctx, &io);
1208 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1209 fnum = io.ntcreatex.out.file.fnum;
1210 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1212 ZERO_STRUCT(break_info);
1214 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1215 status = smb_raw_open(cli2->tree, tctx, &io);
1216 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1218 torture_wait_for_oplock_break(tctx);
1219 CHECK_VAL(break_info.count, 1);
1220 CHECK_VAL(break_info.fnum, fnum);
1221 CHECK_VAL(break_info.level, 1);
1222 CHECK_VAL(break_info.failures, 0);
1224 smbcli_close(cli1->tree, fnum);
1226 done:
1227 smb_raw_exit(cli1->session);
1228 smb_raw_exit(cli2->session);
1229 smbcli_deltree(cli1->tree, BASEDIR);
1230 return ret;
1233 static bool test_raw_oplock_batch6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1235 const char *fname = BASEDIR "\\test_batch6.dat";
1236 NTSTATUS status;
1237 bool ret = true;
1238 union smb_open io;
1239 uint16_t fnum=0, fnum2=0;
1240 char c = 0;
1242 if (!torture_setup_dir(cli1, BASEDIR)) {
1243 return false;
1246 /* cleanup */
1247 smbcli_unlink(cli1->tree, fname);
1249 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1250 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1253 base ntcreatex parms
1255 io.generic.level = RAW_OPEN_NTCREATEX;
1256 io.ntcreatex.in.root_fid.fnum = 0;
1257 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1258 io.ntcreatex.in.alloc_size = 0;
1259 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1260 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1261 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1262 io.ntcreatex.in.create_options = 0;
1263 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1264 io.ntcreatex.in.security_flags = 0;
1265 io.ntcreatex.in.fname = fname;
1267 torture_comment(tctx, "BATCH6: a 2nd open should give a break to level II if the first open allowed shared read\n");
1268 ZERO_STRUCT(break_info);
1270 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
1271 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
1272 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1273 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1274 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1275 status = smb_raw_open(cli1->tree, tctx, &io);
1276 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1277 fnum = io.ntcreatex.out.file.fnum;
1278 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1280 ZERO_STRUCT(break_info);
1282 status = smb_raw_open(cli2->tree, tctx, &io);
1283 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1284 fnum2 = io.ntcreatex.out.file.fnum;
1285 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1287 //torture_wait_for_oplock_break(tctx);
1288 CHECK_VAL(break_info.count, 1);
1289 CHECK_VAL(break_info.fnum, fnum);
1290 CHECK_VAL(break_info.level, 1);
1291 CHECK_VAL(break_info.failures, 0);
1292 ZERO_STRUCT(break_info);
1294 torture_comment(tctx, "write should trigger a break to none on both\n");
1295 smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
1297 /* We expect two breaks */
1298 torture_wait_for_oplock_break(tctx);
1299 torture_wait_for_oplock_break(tctx);
1301 CHECK_VAL(break_info.count, 2);
1302 CHECK_VAL(break_info.level, 0);
1303 CHECK_VAL(break_info.failures, 0);
1305 smbcli_close(cli1->tree, fnum);
1306 smbcli_close(cli2->tree, fnum2);
1308 done:
1309 smb_raw_exit(cli1->session);
1310 smb_raw_exit(cli2->session);
1311 smbcli_deltree(cli1->tree, BASEDIR);
1312 return ret;
1315 static bool test_raw_oplock_batch7(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1317 const char *fname = BASEDIR "\\test_batch7.dat";
1318 NTSTATUS status;
1319 bool ret = true;
1320 union smb_open io;
1321 uint16_t fnum=0, fnum2=0;
1323 if (!torture_setup_dir(cli1, BASEDIR)) {
1324 return false;
1327 /* cleanup */
1328 smbcli_unlink(cli1->tree, fname);
1330 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1333 base ntcreatex parms
1335 io.generic.level = RAW_OPEN_NTCREATEX;
1336 io.ntcreatex.in.root_fid.fnum = 0;
1337 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1338 io.ntcreatex.in.alloc_size = 0;
1339 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1340 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1341 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1342 io.ntcreatex.in.create_options = 0;
1343 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1344 io.ntcreatex.in.security_flags = 0;
1345 io.ntcreatex.in.fname = fname;
1347 torture_comment(tctx, "BATCH7: a 2nd open should get an oplock when we close instead of ack\n");
1348 ZERO_STRUCT(break_info);
1349 smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
1351 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1352 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1353 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1354 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1355 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1356 status = smb_raw_open(cli1->tree, tctx, &io);
1357 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1358 fnum2 = io.ntcreatex.out.file.fnum;
1359 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1361 ZERO_STRUCT(break_info);
1363 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1364 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1365 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1366 status = smb_raw_open(cli2->tree, tctx, &io);
1367 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1368 fnum = io.ntcreatex.out.file.fnum;
1369 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1371 torture_wait_for_oplock_break(tctx);
1372 CHECK_VAL(break_info.count, 1);
1373 CHECK_VAL(break_info.fnum, fnum2);
1374 CHECK_VAL(break_info.level, 1);
1375 CHECK_VAL(break_info.failures, 0);
1377 smbcli_close(cli2->tree, fnum);
1379 done:
1380 smb_raw_exit(cli1->session);
1381 smb_raw_exit(cli2->session);
1382 smbcli_deltree(cli1->tree, BASEDIR);
1383 return ret;
1386 static bool test_raw_oplock_batch8(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1388 const char *fname = BASEDIR "\\test_batch8.dat";
1389 NTSTATUS status;
1390 bool ret = true;
1391 union smb_open io;
1392 uint16_t fnum=0, fnum2=0;
1394 if (!torture_setup_dir(cli1, BASEDIR)) {
1395 return false;
1398 /* cleanup */
1399 smbcli_unlink(cli1->tree, fname);
1401 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1404 base ntcreatex parms
1406 io.generic.level = RAW_OPEN_NTCREATEX;
1407 io.ntcreatex.in.root_fid.fnum = 0;
1408 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1409 io.ntcreatex.in.alloc_size = 0;
1410 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1411 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1412 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1413 io.ntcreatex.in.create_options = 0;
1414 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1415 io.ntcreatex.in.security_flags = 0;
1416 io.ntcreatex.in.fname = fname;
1418 torture_comment(tctx, "BATCH8: open with batch oplock\n");
1419 ZERO_STRUCT(break_info);
1420 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1422 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1423 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1424 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1425 status = smb_raw_open(cli1->tree, tctx, &io);
1426 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1427 fnum = io.ntcreatex.out.file.fnum;
1428 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1430 ZERO_STRUCT(break_info);
1431 torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
1433 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1434 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1435 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1436 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1437 status = smb_raw_open(cli2->tree, tctx, &io);
1438 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1439 fnum2 = io.ntcreatex.out.file.fnum;
1440 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
1441 torture_wait_for_oplock_break(tctx);
1442 CHECK_VAL(break_info.count, 0);
1443 CHECK_VAL(break_info.failures, 0);
1445 smbcli_close(cli1->tree, fnum);
1446 smbcli_close(cli2->tree, fnum2);
1448 done:
1449 smb_raw_exit(cli1->session);
1450 smb_raw_exit(cli2->session);
1451 smbcli_deltree(cli1->tree, BASEDIR);
1452 return ret;
1455 static bool test_raw_oplock_batch9(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1457 const char *fname = BASEDIR "\\test_batch9.dat";
1458 NTSTATUS status;
1459 bool ret = true;
1460 union smb_open io;
1461 uint16_t fnum=0, fnum2=0;
1462 char c = 0;
1464 if (!torture_setup_dir(cli1, BASEDIR)) {
1465 return false;
1468 /* cleanup */
1469 smbcli_unlink(cli1->tree, fname);
1471 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1474 base ntcreatex parms
1476 io.generic.level = RAW_OPEN_NTCREATEX;
1477 io.ntcreatex.in.root_fid.fnum = 0;
1478 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1479 io.ntcreatex.in.alloc_size = 0;
1480 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1481 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1482 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1483 io.ntcreatex.in.create_options = 0;
1484 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1485 io.ntcreatex.in.security_flags = 0;
1486 io.ntcreatex.in.fname = fname;
1488 torture_comment(tctx, "BATCH9: open with attributes only can create file\n");
1490 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1491 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1492 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1493 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1494 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1495 status = smb_raw_open(cli1->tree, tctx, &io);
1496 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1497 fnum = io.ntcreatex.out.file.fnum;
1498 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1500 torture_comment(tctx, "Subsequent normal open should break oplock on attribute only open to level II\n");
1502 ZERO_STRUCT(break_info);
1503 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1505 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1506 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1507 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1508 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1509 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1510 status = smb_raw_open(cli2->tree, tctx, &io);
1511 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1512 fnum2 = io.ntcreatex.out.file.fnum;
1513 torture_wait_for_oplock_break(tctx);
1514 CHECK_VAL(break_info.count, 1);
1515 CHECK_VAL(break_info.fnum, fnum);
1516 CHECK_VAL(break_info.failures, 0);
1517 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1518 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1519 smbcli_close(cli2->tree, fnum2);
1521 torture_comment(tctx, "third oplocked open should grant level2 without break\n");
1522 ZERO_STRUCT(break_info);
1523 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1524 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1525 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1526 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1527 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1528 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1529 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1530 status = smb_raw_open(cli2->tree, tctx, &io);
1531 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1532 fnum2 = io.ntcreatex.out.file.fnum;
1533 torture_wait_for_oplock_break(tctx);
1534 CHECK_VAL(break_info.count, 0);
1535 CHECK_VAL(break_info.failures, 0);
1536 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1538 ZERO_STRUCT(break_info);
1540 torture_comment(tctx, "write should trigger a break to none on both\n");
1541 smbcli_write(cli2->tree, fnum2, 0, &c, 0, 1);
1543 /* We expect two breaks */
1544 torture_wait_for_oplock_break(tctx);
1545 torture_wait_for_oplock_break(tctx);
1547 CHECK_VAL(break_info.count, 2);
1548 CHECK_VAL(break_info.level, 0);
1549 CHECK_VAL(break_info.failures, 0);
1551 smbcli_close(cli1->tree, fnum);
1552 smbcli_close(cli2->tree, fnum2);
1554 done:
1555 smb_raw_exit(cli1->session);
1556 smb_raw_exit(cli2->session);
1557 smbcli_deltree(cli1->tree, BASEDIR);
1558 return ret;
1561 static bool test_raw_oplock_batch10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1563 const char *fname = BASEDIR "\\test_batch10.dat";
1564 NTSTATUS status;
1565 bool ret = true;
1566 union smb_open io;
1567 uint16_t fnum=0, fnum2=0;
1569 if (!torture_setup_dir(cli1, BASEDIR)) {
1570 return false;
1573 /* cleanup */
1574 smbcli_unlink(cli1->tree, fname);
1576 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1579 base ntcreatex parms
1581 io.generic.level = RAW_OPEN_NTCREATEX;
1582 io.ntcreatex.in.root_fid.fnum = 0;
1583 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1584 io.ntcreatex.in.alloc_size = 0;
1585 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1586 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1587 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1588 io.ntcreatex.in.create_options = 0;
1589 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1590 io.ntcreatex.in.security_flags = 0;
1591 io.ntcreatex.in.fname = fname;
1593 torture_comment(tctx, "BATCH10: Open with oplock after a non-oplock open should grant level2\n");
1594 ZERO_STRUCT(break_info);
1595 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1596 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1597 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1598 NTCREATEX_SHARE_ACCESS_WRITE|
1599 NTCREATEX_SHARE_ACCESS_DELETE;
1600 status = smb_raw_open(cli1->tree, tctx, &io);
1601 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1602 fnum = io.ntcreatex.out.file.fnum;
1603 torture_wait_for_oplock_break(tctx);
1604 CHECK_VAL(break_info.count, 0);
1605 CHECK_VAL(break_info.failures, 0);
1606 CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
1608 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1610 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1611 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1612 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1613 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1614 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1615 NTCREATEX_SHARE_ACCESS_WRITE|
1616 NTCREATEX_SHARE_ACCESS_DELETE;
1617 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1618 status = smb_raw_open(cli2->tree, tctx, &io);
1619 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1620 fnum2 = io.ntcreatex.out.file.fnum;
1621 torture_wait_for_oplock_break(tctx);
1622 CHECK_VAL(break_info.count, 0);
1623 CHECK_VAL(break_info.failures, 0);
1624 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1626 torture_comment(tctx, "write should trigger a break to none\n");
1628 union smb_write wr;
1629 wr.write.level = RAW_WRITE_WRITE;
1630 wr.write.in.file.fnum = fnum;
1631 wr.write.in.count = 1;
1632 wr.write.in.offset = 0;
1633 wr.write.in.remaining = 0;
1634 wr.write.in.data = (const uint8_t *)"x";
1635 status = smb_raw_write(cli1->tree, &wr);
1636 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1639 torture_wait_for_oplock_break(tctx);
1641 CHECK_VAL(break_info.count, 1);
1642 CHECK_VAL(break_info.fnum, fnum2);
1643 CHECK_VAL(break_info.level, 0);
1644 CHECK_VAL(break_info.failures, 0);
1646 smbcli_close(cli1->tree, fnum);
1647 smbcli_close(cli2->tree, fnum2);
1649 done:
1650 smb_raw_exit(cli1->session);
1651 smb_raw_exit(cli2->session);
1652 smbcli_deltree(cli1->tree, BASEDIR);
1653 return ret;
1656 static bool test_raw_oplock_batch11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1658 const char *fname = BASEDIR "\\test_batch11.dat";
1659 NTSTATUS status;
1660 bool ret = true;
1661 union smb_open io;
1662 union smb_setfileinfo sfi;
1663 uint16_t fnum=0;
1665 if (!torture_setup_dir(cli1, BASEDIR)) {
1666 return false;
1669 /* cleanup */
1670 smbcli_unlink(cli1->tree, fname);
1672 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1675 base ntcreatex parms
1677 io.generic.level = RAW_OPEN_NTCREATEX;
1678 io.ntcreatex.in.root_fid.fnum = 0;
1679 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1680 io.ntcreatex.in.alloc_size = 0;
1681 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1682 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE;
1683 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1684 io.ntcreatex.in.create_options = 0;
1685 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1686 io.ntcreatex.in.security_flags = 0;
1687 io.ntcreatex.in.fname = fname;
1689 /* Test if a set-eof on pathname breaks an exclusive oplock. */
1690 torture_comment(tctx, "BATCH11: Test if setpathinfo set EOF breaks oplocks.\n");
1692 ZERO_STRUCT(break_info);
1694 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1695 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1696 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1697 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1698 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1699 NTCREATEX_SHARE_ACCESS_WRITE|
1700 NTCREATEX_SHARE_ACCESS_DELETE;
1701 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1702 status = smb_raw_open(cli1->tree, tctx, &io);
1703 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1704 fnum = io.ntcreatex.out.file.fnum;
1705 torture_wait_for_oplock_break(tctx);
1706 CHECK_VAL(break_info.count, 0);
1707 CHECK_VAL(break_info.failures, 0);
1708 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1710 ZERO_STRUCT(sfi);
1711 sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1712 sfi.generic.in.file.path = fname;
1713 sfi.end_of_file_info.in.size = 100;
1715 status = smb_raw_setpathinfo(cli2->tree, &sfi);
1716 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1718 torture_wait_for_oplock_break(tctx);
1719 CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
1720 CHECK_VAL(break_info.failures, 0);
1721 CHECK_VAL(break_info.level, 0);
1723 smbcli_close(cli1->tree, fnum);
1725 done:
1726 smb_raw_exit(cli1->session);
1727 smb_raw_exit(cli2->session);
1728 smbcli_deltree(cli1->tree, BASEDIR);
1729 return ret;
1732 static bool test_raw_oplock_batch12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1734 const char *fname = BASEDIR "\\test_batch12.dat";
1735 NTSTATUS status;
1736 bool ret = true;
1737 union smb_open io;
1738 union smb_setfileinfo sfi;
1739 uint16_t fnum=0;
1741 if (!torture_setup_dir(cli1, BASEDIR)) {
1742 return false;
1745 /* cleanup */
1746 smbcli_unlink(cli1->tree, fname);
1748 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1751 base ntcreatex parms
1753 io.generic.level = RAW_OPEN_NTCREATEX;
1754 io.ntcreatex.in.root_fid.fnum = 0;
1755 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1756 io.ntcreatex.in.alloc_size = 0;
1757 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1758 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1759 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1760 io.ntcreatex.in.create_options = 0;
1761 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1762 io.ntcreatex.in.security_flags = 0;
1763 io.ntcreatex.in.fname = fname;
1765 /* Test if a set-allocation size on pathname breaks an exclusive oplock. */
1766 torture_comment(tctx, "BATCH12: Test if setpathinfo allocation size breaks oplocks.\n");
1768 ZERO_STRUCT(break_info);
1769 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1771 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1772 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1773 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1774 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1775 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1776 NTCREATEX_SHARE_ACCESS_WRITE|
1777 NTCREATEX_SHARE_ACCESS_DELETE;
1778 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1779 status = smb_raw_open(cli1->tree, tctx, &io);
1780 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1781 fnum = io.ntcreatex.out.file.fnum;
1782 torture_wait_for_oplock_break(tctx);
1783 CHECK_VAL(break_info.count, 0);
1784 CHECK_VAL(break_info.failures, 0);
1785 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1787 ZERO_STRUCT(sfi);
1788 sfi.generic.level = SMB_SFILEINFO_ALLOCATION_INFORMATION;
1789 sfi.generic.in.file.path = fname;
1790 sfi.allocation_info.in.alloc_size = 65536 * 8;
1792 status = smb_raw_setpathinfo(cli2->tree, &sfi);
1793 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1795 torture_wait_for_oplock_break(tctx);
1796 CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
1797 CHECK_VAL(break_info.failures, 0);
1798 CHECK_VAL(break_info.level, 0);
1800 smbcli_close(cli1->tree, fnum);
1802 done:
1803 smb_raw_exit(cli1->session);
1804 smb_raw_exit(cli2->session);
1805 smbcli_deltree(cli1->tree, BASEDIR);
1806 return ret;
1809 static bool test_raw_oplock_batch13(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1811 const char *fname = BASEDIR "\\test_batch13.dat";
1812 NTSTATUS status;
1813 bool ret = true;
1814 union smb_open io;
1815 uint16_t fnum=0, fnum2=0;
1817 if (!torture_setup_dir(cli1, BASEDIR)) {
1818 return false;
1821 /* cleanup */
1822 smbcli_unlink(cli1->tree, fname);
1824 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1825 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
1828 base ntcreatex parms
1830 io.generic.level = RAW_OPEN_NTCREATEX;
1831 io.ntcreatex.in.root_fid.fnum = 0;
1832 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1833 io.ntcreatex.in.alloc_size = 0;
1834 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1835 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1836 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1837 io.ntcreatex.in.create_options = 0;
1838 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1839 io.ntcreatex.in.security_flags = 0;
1840 io.ntcreatex.in.fname = fname;
1842 torture_comment(tctx, "BATCH13: open with batch oplock\n");
1843 ZERO_STRUCT(break_info);
1845 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1846 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1847 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1848 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1849 NTCREATEX_SHARE_ACCESS_WRITE|
1850 NTCREATEX_SHARE_ACCESS_DELETE;
1851 status = smb_raw_open(cli1->tree, tctx, &io);
1852 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1853 fnum = io.ntcreatex.out.file.fnum;
1854 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1856 ZERO_STRUCT(break_info);
1858 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE dispostion causes oplock break\n");
1860 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1861 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1862 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1863 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1864 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1865 NTCREATEX_SHARE_ACCESS_WRITE|
1866 NTCREATEX_SHARE_ACCESS_DELETE;
1867 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
1868 status = smb_raw_open(cli2->tree, tctx, &io);
1869 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1870 fnum2 = io.ntcreatex.out.file.fnum;
1871 torture_wait_for_oplock_break(tctx);
1872 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1873 CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
1874 CHECK_VAL(break_info.failures, 0);
1876 smbcli_close(cli1->tree, fnum);
1877 smbcli_close(cli2->tree, fnum2);
1879 done:
1880 smb_raw_exit(cli1->session);
1881 smb_raw_exit(cli2->session);
1882 smbcli_deltree(cli1->tree, BASEDIR);
1883 return ret;
1886 static bool test_raw_oplock_batch14(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1888 const char *fname = BASEDIR "\\test_batch14.dat";
1889 NTSTATUS status;
1890 bool ret = true;
1891 union smb_open io;
1892 uint16_t fnum=0, fnum2=0;
1894 if (!torture_setup_dir(cli1, BASEDIR)) {
1895 return false;
1898 /* cleanup */
1899 smbcli_unlink(cli1->tree, fname);
1901 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1904 base ntcreatex parms
1906 io.generic.level = RAW_OPEN_NTCREATEX;
1907 io.ntcreatex.in.root_fid.fnum = 0;
1908 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1909 io.ntcreatex.in.alloc_size = 0;
1910 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1911 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1912 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1913 io.ntcreatex.in.create_options = 0;
1914 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1915 io.ntcreatex.in.security_flags = 0;
1916 io.ntcreatex.in.fname = fname;
1918 torture_comment(tctx, "BATCH14: open with batch oplock\n");
1919 ZERO_STRUCT(break_info);
1921 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1922 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1923 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1924 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1925 NTCREATEX_SHARE_ACCESS_WRITE|
1926 NTCREATEX_SHARE_ACCESS_DELETE;
1927 status = smb_raw_open(cli1->tree, tctx, &io);
1928 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1929 fnum = io.ntcreatex.out.file.fnum;
1930 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1932 ZERO_STRUCT(break_info);
1934 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_SUPERSEDE dispostion causes oplock break\n");
1936 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1937 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1938 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1939 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1940 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1941 NTCREATEX_SHARE_ACCESS_WRITE|
1942 NTCREATEX_SHARE_ACCESS_DELETE;
1943 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
1944 status = smb_raw_open(cli2->tree, tctx, &io);
1945 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1946 fnum2 = io.ntcreatex.out.file.fnum;
1947 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1949 torture_wait_for_oplock_break(tctx);
1950 CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
1951 CHECK_VAL(break_info.failures, 0);
1953 smbcli_close(cli1->tree, fnum);
1954 smbcli_close(cli2->tree, fnum2);
1955 done:
1956 smb_raw_exit(cli1->session);
1957 smb_raw_exit(cli2->session);
1958 smbcli_deltree(cli1->tree, BASEDIR);
1959 return ret;
1962 static bool test_raw_oplock_batch15(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1964 const char *fname = BASEDIR "\\test_batch15.dat";
1965 NTSTATUS status;
1966 bool ret = true;
1967 union smb_open io;
1968 union smb_fileinfo qfi;
1969 uint16_t fnum=0;
1971 if (!torture_setup_dir(cli1, BASEDIR)) {
1972 return false;
1975 /* cleanup */
1976 smbcli_unlink(cli1->tree, fname);
1978 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1981 base ntcreatex parms
1983 io.generic.level = RAW_OPEN_NTCREATEX;
1984 io.ntcreatex.in.root_fid.fnum = 0;
1985 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1986 io.ntcreatex.in.alloc_size = 0;
1987 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1988 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1989 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1990 io.ntcreatex.in.create_options = 0;
1991 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1992 io.ntcreatex.in.security_flags = 0;
1993 io.ntcreatex.in.fname = fname;
1995 /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
1996 torture_comment(tctx, "BATCH15: Test if qpathinfo all info breaks a batch oplock (should not).\n");
1998 ZERO_STRUCT(break_info);
2000 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2001 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2002 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2003 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2004 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2005 NTCREATEX_SHARE_ACCESS_WRITE|
2006 NTCREATEX_SHARE_ACCESS_DELETE;
2007 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2008 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2009 status = smb_raw_open(cli1->tree, tctx, &io);
2010 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2011 fnum = io.ntcreatex.out.file.fnum;
2013 torture_wait_for_oplock_break(tctx);
2014 CHECK_VAL(break_info.count, 0);
2015 CHECK_VAL(break_info.failures, 0);
2016 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2018 ZERO_STRUCT(qfi);
2019 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2020 qfi.generic.in.file.path = fname;
2022 status = smb_raw_pathinfo(cli2->tree, tctx, &qfi);
2023 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2025 torture_wait_for_oplock_break(tctx);
2026 CHECK_VAL(break_info.count, 0);
2028 smbcli_close(cli1->tree, fnum);
2030 done:
2031 smb_raw_exit(cli1->session);
2032 smb_raw_exit(cli2->session);
2033 smbcli_deltree(cli1->tree, BASEDIR);
2034 return ret;
2037 static bool test_raw_oplock_batch16(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2039 const char *fname = BASEDIR "\\test_batch16.dat";
2040 NTSTATUS status;
2041 bool ret = true;
2042 union smb_open io;
2043 uint16_t fnum=0, fnum2=0;
2045 if (!torture_setup_dir(cli1, BASEDIR)) {
2046 return false;
2049 /* cleanup */
2050 smbcli_unlink(cli1->tree, fname);
2052 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2053 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
2056 base ntcreatex parms
2058 io.generic.level = RAW_OPEN_NTCREATEX;
2059 io.ntcreatex.in.root_fid.fnum = 0;
2060 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2061 io.ntcreatex.in.alloc_size = 0;
2062 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2063 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2064 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2065 io.ntcreatex.in.create_options = 0;
2066 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2067 io.ntcreatex.in.security_flags = 0;
2068 io.ntcreatex.in.fname = fname;
2070 torture_comment(tctx, "BATCH16: open with batch oplock\n");
2071 ZERO_STRUCT(break_info);
2073 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2074 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2075 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2076 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2077 NTCREATEX_SHARE_ACCESS_WRITE|
2078 NTCREATEX_SHARE_ACCESS_DELETE;
2079 status = smb_raw_open(cli1->tree, tctx, &io);
2080 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2081 fnum = io.ntcreatex.out.file.fnum;
2082 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2084 ZERO_STRUCT(break_info);
2086 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
2088 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2089 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2090 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2091 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
2092 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2093 NTCREATEX_SHARE_ACCESS_WRITE|
2094 NTCREATEX_SHARE_ACCESS_DELETE;
2095 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2096 status = smb_raw_open(cli2->tree, tctx, &io);
2097 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2098 fnum2 = io.ntcreatex.out.file.fnum;
2099 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2101 torture_wait_for_oplock_break(tctx);
2102 CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
2103 CHECK_VAL(break_info.failures, 0);
2105 smbcli_close(cli1->tree, fnum);
2106 smbcli_close(cli2->tree, fnum2);
2108 done:
2109 smb_raw_exit(cli1->session);
2110 smb_raw_exit(cli2->session);
2111 smbcli_deltree(cli1->tree, BASEDIR);
2112 return ret;
2115 static bool test_raw_oplock_batch17(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2117 const char *fname1 = BASEDIR "\\test_batch17_1.dat";
2118 const char *fname2 = BASEDIR "\\test_batch17_2.dat";
2119 NTSTATUS status;
2120 bool ret = true;
2121 union smb_open io;
2122 union smb_rename rn;
2123 uint16_t fnum=0;
2125 if (!torture_setup_dir(cli1, BASEDIR)) {
2126 return false;
2129 /* cleanup */
2130 smbcli_unlink(cli1->tree, fname1);
2131 smbcli_unlink(cli1->tree, fname2);
2133 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2136 base ntcreatex parms
2138 io.generic.level = RAW_OPEN_NTCREATEX;
2139 io.ntcreatex.in.root_fid.fnum = 0;
2140 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2141 io.ntcreatex.in.alloc_size = 0;
2142 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2143 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2144 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2145 io.ntcreatex.in.create_options = 0;
2146 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2147 io.ntcreatex.in.security_flags = 0;
2148 io.ntcreatex.in.fname = fname1;
2150 torture_comment(tctx, "BATCH17: open a file with an batch oplock (share mode: none)\n");
2152 ZERO_STRUCT(break_info);
2153 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2154 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2155 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2157 status = smb_raw_open(cli1->tree, tctx, &io);
2158 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2159 fnum = io.ntcreatex.out.file.fnum;
2160 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2162 torture_comment(tctx, "rename should trigger a break\n");
2163 ZERO_STRUCT(rn);
2164 rn.generic.level = RAW_RENAME_RENAME;
2165 rn.rename.in.pattern1 = fname1;
2166 rn.rename.in.pattern2 = fname2;
2167 rn.rename.in.attrib = 0;
2169 torture_comment(tctx, "trying rename while first file open\n");
2170 status = smb_raw_rename(cli2->tree, &rn);
2171 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2173 torture_wait_for_oplock_break(tctx);
2174 CHECK_VAL(break_info.count, 1);
2175 CHECK_VAL(break_info.failures, 0);
2176 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
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 static bool test_raw_oplock_batch18(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2189 const char *fname1 = BASEDIR "\\test_batch18_1.dat";
2190 const char *fname2 = BASEDIR "\\test_batch18_2.dat";
2191 NTSTATUS status;
2192 bool ret = true;
2193 union smb_open io;
2194 union smb_rename rn;
2195 uint16_t fnum=0;
2197 if (!torture_setup_dir(cli1, BASEDIR)) {
2198 return false;
2201 /* cleanup */
2202 smbcli_unlink(cli1->tree, fname1);
2203 smbcli_unlink(cli1->tree, fname2);
2205 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2208 base ntcreatex parms
2210 io.generic.level = RAW_OPEN_NTCREATEX;
2211 io.ntcreatex.in.root_fid.fnum = 0;
2212 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2213 io.ntcreatex.in.alloc_size = 0;
2214 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2215 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2216 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2217 io.ntcreatex.in.create_options = 0;
2218 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2219 io.ntcreatex.in.security_flags = 0;
2220 io.ntcreatex.in.fname = fname1;
2222 torture_comment(tctx, "BATCH18: open a file with an batch oplock (share mode: none)\n");
2224 ZERO_STRUCT(break_info);
2225 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2226 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2227 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2229 status = smb_raw_open(cli1->tree, tctx, &io);
2230 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2231 fnum = io.ntcreatex.out.file.fnum;
2232 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2234 torture_comment(tctx, "ntrename should trigger a break\n");
2235 ZERO_STRUCT(rn);
2236 rn.generic.level = RAW_RENAME_NTRENAME;
2237 rn.ntrename.in.attrib = 0;
2238 rn.ntrename.in.flags = RENAME_FLAG_RENAME;
2239 rn.ntrename.in.old_name = fname1;
2240 rn.ntrename.in.new_name = fname2;
2241 torture_comment(tctx, "trying rename while first file open\n");
2242 status = smb_raw_rename(cli2->tree, &rn);
2243 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2245 torture_wait_for_oplock_break(tctx);
2246 CHECK_VAL(break_info.count, 1);
2247 CHECK_VAL(break_info.failures, 0);
2248 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2250 smbcli_close(cli1->tree, fnum);
2252 done:
2253 smb_raw_exit(cli1->session);
2254 smb_raw_exit(cli2->session);
2255 smbcli_deltree(cli1->tree, BASEDIR);
2256 return ret;
2259 static bool test_raw_oplock_batch19(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2261 const char *fname1 = BASEDIR "\\test_batch19_1.dat";
2262 const char *fname2 = BASEDIR "\\test_batch19_2.dat";
2263 const char *fname3 = BASEDIR "\\test_batch19_3.dat";
2264 NTSTATUS status;
2265 bool ret = true;
2266 union smb_open io;
2267 union smb_fileinfo qfi;
2268 union smb_setfileinfo sfi;
2269 uint16_t fnum=0;
2271 if (!torture_setup_dir(cli1, BASEDIR)) {
2272 return false;
2275 /* cleanup */
2276 smbcli_unlink(cli1->tree, fname1);
2277 smbcli_unlink(cli1->tree, fname2);
2278 smbcli_unlink(cli1->tree, fname3);
2280 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2283 base ntcreatex parms
2285 io.generic.level = RAW_OPEN_NTCREATEX;
2286 io.ntcreatex.in.root_fid.fnum = 0;
2287 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2288 io.ntcreatex.in.alloc_size = 0;
2289 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2290 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2291 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
2292 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2293 io.ntcreatex.in.create_options = 0;
2294 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2295 io.ntcreatex.in.security_flags = 0;
2296 io.ntcreatex.in.fname = fname1;
2298 torture_comment(tctx, "BATCH19: open a file with an batch oplock (share mode: none)\n");
2299 ZERO_STRUCT(break_info);
2300 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2301 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2302 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2303 status = smb_raw_open(cli1->tree, tctx, &io);
2304 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2305 fnum = io.ntcreatex.out.file.fnum;
2306 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2308 torture_comment(tctx, "setpathinfo rename info should trigger a break "
2309 "to none\n");
2310 ZERO_STRUCT(sfi);
2311 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2312 sfi.generic.in.file.path = fname1;
2313 sfi.rename_information.in.overwrite = 0;
2314 sfi.rename_information.in.root_fid = 0;
2315 sfi.rename_information.in.new_name = fname2+strlen(BASEDIR)+1;
2317 status = smb_raw_setpathinfo(cli2->tree, &sfi);
2318 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2320 torture_wait_for_oplock_break(tctx);
2322 CHECK_VAL(break_info.failures, 0);
2324 if (TARGET_IS_WINXP(tctx)) {
2325 /* Win XP breaks to level2. */
2326 CHECK_VAL(break_info.count, 1);
2327 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2328 } else if (TARGET_IS_W2K3(tctx) || TARGET_IS_W2K8(tctx) ||
2329 TARGET_IS_SAMBA3(tctx) || TARGET_IS_SAMBA4(tctx)) {
2330 /* Win2K3/2k8 incorrectly doesn't break at all. */
2331 CHECK_VAL(break_info.count, 0);
2332 } else {
2333 /* win7/2k8r2 break to none. */
2334 CHECK_VAL(break_info.count, 1);
2335 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
2338 ZERO_STRUCT(qfi);
2339 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2340 qfi.generic.in.file.fnum = fnum;
2342 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2343 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2344 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2346 /* Close and re-open file with oplock. */
2347 smbcli_close(cli1->tree, fnum);
2348 status = smb_raw_open(cli1->tree, tctx, &io);
2349 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2350 fnum = io.ntcreatex.out.file.fnum;
2351 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2353 torture_comment(tctx, "setfileinfo rename info on a client's own fid "
2354 "should not trigger a break nor a violation\n");
2355 ZERO_STRUCT(break_info);
2356 ZERO_STRUCT(sfi);
2357 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2358 sfi.generic.in.file.fnum = fnum;
2359 sfi.rename_information.in.overwrite = 0;
2360 sfi.rename_information.in.root_fid = 0;
2361 sfi.rename_information.in.new_name = fname3+strlen(BASEDIR)+1;
2363 status = smb_raw_setfileinfo(cli1->tree, &sfi);
2364 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2366 torture_wait_for_oplock_break(tctx);
2367 if (TARGET_IS_WINXP(tctx)) {
2368 /* XP incorrectly breaks to level2. */
2369 CHECK_VAL(break_info.count, 1);
2370 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2371 } else {
2372 CHECK_VAL(break_info.count, 0);
2375 ZERO_STRUCT(qfi);
2376 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2377 qfi.generic.in.file.fnum = fnum;
2379 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2380 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2381 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2383 done:
2384 smbcli_close(cli1->tree, fnum);
2385 smb_raw_exit(cli1->session);
2386 smb_raw_exit(cli2->session);
2387 smbcli_deltree(cli1->tree, BASEDIR);
2388 return ret;
2391 /****************************************************
2392 Called from raw-rename - we need oplock handling for
2393 this test so this is why it's in oplock.c, not rename.c
2394 ****************************************************/
2396 bool test_trans2rename(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2398 const char *fname1 = BASEDIR "\\test_trans2rename_1.dat";
2399 const char *fname2 = BASEDIR "\\test_trans2rename_2.dat";
2400 const char *fname3 = BASEDIR "\\test_trans2rename_3.dat";
2401 NTSTATUS status;
2402 bool ret = true;
2403 union smb_open io;
2404 union smb_fileinfo qfi;
2405 union smb_setfileinfo sfi;
2406 uint16_t fnum=0;
2408 if (!torture_setup_dir(cli1, BASEDIR)) {
2409 return false;
2412 /* cleanup */
2413 smbcli_unlink(cli1->tree, fname1);
2414 smbcli_unlink(cli1->tree, fname2);
2415 smbcli_unlink(cli1->tree, fname3);
2417 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2420 base ntcreatex parms
2422 io.generic.level = RAW_OPEN_NTCREATEX;
2423 io.ntcreatex.in.root_fid.fnum = 0;
2424 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2425 io.ntcreatex.in.alloc_size = 0;
2426 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2427 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2428 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
2429 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2430 io.ntcreatex.in.create_options = 0;
2431 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2432 io.ntcreatex.in.security_flags = 0;
2433 io.ntcreatex.in.fname = fname1;
2435 torture_comment(tctx, "open a file with an exclusive oplock (share mode: none)\n");
2436 ZERO_STRUCT(break_info);
2437 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2438 NTCREATEX_FLAGS_REQUEST_OPLOCK;
2439 status = smb_raw_open(cli1->tree, tctx, &io);
2440 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2441 fnum = io.ntcreatex.out.file.fnum;
2442 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
2444 torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
2445 ZERO_STRUCT(sfi);
2446 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2447 sfi.generic.in.file.path = fname1;
2448 sfi.rename_information.in.overwrite = 0;
2449 sfi.rename_information.in.root_fid = 0;
2450 sfi.rename_information.in.new_name = fname2+strlen(BASEDIR)+1;
2452 status = smb_raw_setpathinfo(cli2->tree, &sfi);
2454 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2456 torture_wait_for_oplock_break(tctx);
2457 CHECK_VAL(break_info.count, 0);
2459 ZERO_STRUCT(qfi);
2460 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2461 qfi.generic.in.file.fnum = fnum;
2463 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2464 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2465 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2467 torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
2468 ZERO_STRUCT(sfi);
2469 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2470 sfi.generic.in.file.fnum = fnum;
2471 sfi.rename_information.in.overwrite = 0;
2472 sfi.rename_information.in.root_fid = 0;
2473 sfi.rename_information.in.new_name = fname3+strlen(BASEDIR)+1;
2475 status = smb_raw_setfileinfo(cli1->tree, &sfi);
2476 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2478 torture_wait_for_oplock_break(tctx);
2479 CHECK_VAL(break_info.count, 0);
2481 ZERO_STRUCT(qfi);
2482 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2483 qfi.generic.in.file.fnum = fnum;
2485 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2486 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2487 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2489 done:
2490 smbcli_close(cli1->tree, fnum);
2491 smb_raw_exit(cli1->session);
2492 smb_raw_exit(cli2->session);
2493 smbcli_deltree(cli1->tree, BASEDIR);
2494 return ret;
2497 /****************************************************
2498 Called from raw-rename - we need oplock handling for
2499 this test so this is why it's in oplock.c, not rename.c
2500 ****************************************************/
2502 bool test_nttransrename(struct torture_context *tctx, struct smbcli_state *cli1)
2504 const char *fname1 = BASEDIR "\\test_nttransrename_1.dat";
2505 const char *fname2 = BASEDIR "\\test_nttransrename_2.dat";
2506 NTSTATUS status;
2507 bool ret = true;
2508 union smb_open io;
2509 union smb_fileinfo qfi, qpi;
2510 union smb_rename rn;
2511 uint16_t fnum=0;
2513 if (!torture_setup_dir(cli1, BASEDIR)) {
2514 return false;
2517 /* cleanup */
2518 smbcli_unlink(cli1->tree, fname1);
2519 smbcli_unlink(cli1->tree, fname2);
2521 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2524 base ntcreatex parms
2526 io.generic.level = RAW_OPEN_NTCREATEX;
2527 io.ntcreatex.in.root_fid.fnum = 0;
2528 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2529 io.ntcreatex.in.alloc_size = 0;
2530 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2531 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2532 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2533 io.ntcreatex.in.create_options = 0;
2534 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2535 io.ntcreatex.in.security_flags = 0;
2536 io.ntcreatex.in.fname = fname1;
2538 torture_comment(tctx, "nttrans_rename: open a file with an exclusive oplock (share mode: none)\n");
2539 ZERO_STRUCT(break_info);
2540 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2541 NTCREATEX_FLAGS_REQUEST_OPLOCK;
2542 status = smb_raw_open(cli1->tree, tctx, &io);
2543 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2544 fnum = io.ntcreatex.out.file.fnum;
2545 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
2547 torture_comment(tctx, "nttrans_rename: should not trigger a break nor a share mode violation\n");
2548 ZERO_STRUCT(rn);
2549 rn.generic.level = RAW_RENAME_NTTRANS;
2550 rn.nttrans.in.file.fnum = fnum;
2551 rn.nttrans.in.flags = 0;
2552 rn.nttrans.in.new_name = fname2+strlen(BASEDIR)+1;
2554 status = smb_raw_rename(cli1->tree, &rn);
2555 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2557 torture_wait_for_oplock_break(tctx);
2558 CHECK_VAL(break_info.count, 0);
2560 /* w2k3 does nothing, it doesn't rename the file */
2561 torture_comment(tctx, "nttrans_rename: the server should have done nothing\n");
2562 ZERO_STRUCT(qfi);
2563 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2564 qfi.generic.in.file.fnum = fnum;
2566 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2567 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2568 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname1);
2570 ZERO_STRUCT(qpi);
2571 qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2572 qpi.generic.in.file.path = fname1;
2574 status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2575 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2576 CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1);
2578 ZERO_STRUCT(qpi);
2579 qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2580 qpi.generic.in.file.path = fname2;
2582 status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2583 CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2585 torture_comment(tctx, "nttrans_rename: after closing the file the file is still not renamed\n");
2586 status = smbcli_close(cli1->tree, fnum);
2587 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2589 ZERO_STRUCT(qpi);
2590 qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2591 qpi.generic.in.file.path = fname1;
2593 status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2594 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2595 CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1);
2597 ZERO_STRUCT(qpi);
2598 qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2599 qpi.generic.in.file.path = fname2;
2601 status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2602 CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2604 torture_comment(tctx, "nttrans_rename: rename with an invalid handle gives NT_STATUS_INVALID_HANDLE\n");
2605 ZERO_STRUCT(rn);
2606 rn.generic.level = RAW_RENAME_NTTRANS;
2607 rn.nttrans.in.file.fnum = fnum+1;
2608 rn.nttrans.in.flags = 0;
2609 rn.nttrans.in.new_name = fname2+strlen(BASEDIR)+1;
2611 status = smb_raw_rename(cli1->tree, &rn);
2613 CHECK_STATUS(tctx, status, NT_STATUS_INVALID_HANDLE);
2615 done:
2616 smb_raw_exit(cli1->session);
2617 smbcli_deltree(cli1->tree, BASEDIR);
2618 return ret;
2622 static bool test_raw_oplock_batch20(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2624 const char *fname1 = BASEDIR "\\test_batch20_1.dat";
2625 const char *fname2 = BASEDIR "\\test_batch20_2.dat";
2626 const char *fname3 = BASEDIR "\\test_batch20_3.dat";
2627 NTSTATUS status;
2628 bool ret = true;
2629 union smb_open io;
2630 union smb_fileinfo qfi;
2631 union smb_setfileinfo sfi;
2632 uint16_t fnum=0,fnum2=0;
2634 if (!torture_setup_dir(cli1, BASEDIR)) {
2635 return false;
2638 /* cleanup */
2639 smbcli_unlink(cli1->tree, fname1);
2640 smbcli_unlink(cli1->tree, fname2);
2641 smbcli_unlink(cli1->tree, fname3);
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.fnum = 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 = fname1;
2660 torture_comment(tctx, "BATCH20: open a file with an batch oplock (share mode: all)\n");
2661 ZERO_STRUCT(break_info);
2662 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2663 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2664 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2665 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2666 NTCREATEX_SHARE_ACCESS_WRITE|
2667 NTCREATEX_SHARE_ACCESS_DELETE;
2668 status = smb_raw_open(cli1->tree, tctx, &io);
2669 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2670 fnum = io.ntcreatex.out.file.fnum;
2671 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2673 ZERO_STRUCT(sfi);
2674 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2675 sfi.generic.in.file.path = fname1;
2676 sfi.rename_information.in.overwrite = 0;
2677 sfi.rename_information.in.root_fid = 0;
2678 sfi.rename_information.in.new_name = fname2+strlen(BASEDIR)+1;
2680 status = smb_raw_setpathinfo(cli2->tree, &sfi);
2681 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2683 torture_wait_for_oplock_break(tctx);
2684 CHECK_VAL(break_info.failures, 0);
2686 if (TARGET_IS_WINXP(tctx)) {
2687 /* Win XP breaks to level2. */
2688 CHECK_VAL(break_info.count, 1);
2689 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2690 } else if (TARGET_IS_W2K3(tctx) || TARGET_IS_W2K8(tctx) ||
2691 TARGET_IS_SAMBA3(tctx) || TARGET_IS_SAMBA4(tctx)) {
2692 /* Win2K3/2k8 incorrectly doesn't break at all. */
2693 CHECK_VAL(break_info.count, 0);
2694 } else {
2695 /* win7/2k8r2 break to none. */
2696 CHECK_VAL(break_info.count, 1);
2697 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
2700 ZERO_STRUCT(qfi);
2701 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2702 qfi.generic.in.file.fnum = fnum;
2704 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2705 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2706 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2708 torture_comment(tctx, "open a file with the new name an batch oplock (share mode: all)\n");
2709 ZERO_STRUCT(break_info);
2710 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2711 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2712 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2713 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2714 NTCREATEX_SHARE_ACCESS_WRITE|
2715 NTCREATEX_SHARE_ACCESS_DELETE;
2716 io.ntcreatex.in.fname = fname2;
2717 status = smb_raw_open(cli2->tree, tctx, &io);
2718 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2719 fnum2 = io.ntcreatex.out.file.fnum;
2720 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2722 torture_wait_for_oplock_break(tctx);
2724 if (TARGET_IS_WINXP(tctx)) {
2725 /* XP broke to level2, and doesn't break again. */
2726 CHECK_VAL(break_info.count, 0);
2727 } else if (TARGET_IS_W2K3(tctx) || TARGET_IS_W2K8(tctx) ||
2728 TARGET_IS_SAMBA3(tctx) || TARGET_IS_SAMBA4(tctx)) {
2729 /* Win2K3 incorrectly didn't break before so break now. */
2730 CHECK_VAL(break_info.count, 1);
2731 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2732 } else {
2733 /* win7/2k8r2 broke to none, and doesn't break again. */
2734 CHECK_VAL(break_info.count, 0);
2737 ZERO_STRUCT(break_info);
2739 ZERO_STRUCT(sfi);
2740 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2741 sfi.generic.in.file.fnum = fnum;
2742 sfi.rename_information.in.overwrite = 0;
2743 sfi.rename_information.in.root_fid = 0;
2744 sfi.rename_information.in.new_name = fname3+strlen(BASEDIR)+1;
2746 status = smb_raw_setfileinfo(cli1->tree, &sfi);
2747 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2749 torture_wait_for_oplock_break(tctx);
2750 CHECK_VAL(break_info.count, 0);
2752 ZERO_STRUCT(qfi);
2753 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2754 qfi.generic.in.file.fnum = fnum;
2756 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2757 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2758 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2760 ZERO_STRUCT(qfi);
2761 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2762 qfi.generic.in.file.fnum = fnum2;
2764 status = smb_raw_fileinfo(cli2->tree, tctx, &qfi);
2765 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2766 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2769 done:
2770 smbcli_close(cli1->tree, fnum);
2771 smbcli_close(cli2->tree, fnum2);
2772 smb_raw_exit(cli1->session);
2773 smb_raw_exit(cli2->session);
2774 smbcli_deltree(cli1->tree, BASEDIR);
2775 return ret;
2778 static bool test_raw_oplock_batch21(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2780 const char *fname = BASEDIR "\\test_batch21.dat";
2781 NTSTATUS status;
2782 bool ret = true;
2783 union smb_open io;
2784 struct smb_echo e;
2785 uint16_t fnum=0;
2786 char c = 0;
2787 ssize_t wr;
2789 if (!torture_setup_dir(cli1, BASEDIR)) {
2790 return false;
2793 /* cleanup */
2794 smbcli_unlink(cli1->tree, fname);
2796 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2799 base ntcreatex parms
2801 io.generic.level = RAW_OPEN_NTCREATEX;
2802 io.ntcreatex.in.root_fid.fnum = 0;
2803 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2804 io.ntcreatex.in.alloc_size = 0;
2805 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2806 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2807 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2808 io.ntcreatex.in.create_options = 0;
2809 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2810 io.ntcreatex.in.security_flags = 0;
2811 io.ntcreatex.in.fname = fname;
2814 with a batch oplock we get a break
2816 torture_comment(tctx, "BATCH21: open with batch oplock\n");
2817 ZERO_STRUCT(break_info);
2818 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2819 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2820 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2821 status = smb_raw_open(cli1->tree, tctx, &io);
2822 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2823 fnum = io.ntcreatex.out.file.fnum;
2824 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2826 torture_comment(tctx, "writing should not generate a break\n");
2827 wr = smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
2828 CHECK_VAL(wr, 1);
2829 CHECK_STATUS(tctx, smbcli_nt_error(cli1->tree), NT_STATUS_OK);
2831 ZERO_STRUCT(e);
2832 e.in.repeat_count = 1;
2833 status = smb_raw_echo(cli1->transport, &e);
2834 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2836 torture_wait_for_oplock_break(tctx);
2837 CHECK_VAL(break_info.count, 0);
2839 smbcli_close(cli1->tree, fnum);
2841 done:
2842 smb_raw_exit(cli1->session);
2843 smb_raw_exit(cli2->session);
2844 smbcli_deltree(cli1->tree, BASEDIR);
2845 return ret;
2848 static bool test_raw_oplock_batch22(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2850 const char *fname = BASEDIR "\\test_batch22.dat";
2851 NTSTATUS status;
2852 bool ret = true;
2853 union smb_open io;
2854 uint16_t fnum = 0, fnum2 = 0, fnum3 = 0;
2855 struct timeval tv;
2856 int timeout = torture_setting_int(tctx, "oplocktimeout", 30);
2857 int te;
2859 if (!torture_setup_dir(cli1, BASEDIR)) {
2860 return false;
2863 /* cleanup */
2864 smbcli_unlink(cli1->tree, fname);
2866 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2868 base ntcreatex parms
2870 io.generic.level = RAW_OPEN_NTCREATEX;
2871 io.ntcreatex.in.root_fid.fnum = 0;
2872 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2873 io.ntcreatex.in.alloc_size = 0;
2874 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2875 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2876 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2877 io.ntcreatex.in.create_options = 0;
2878 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2879 io.ntcreatex.in.security_flags = 0;
2880 io.ntcreatex.in.fname = fname;
2883 with a batch oplock we get a break
2885 torture_comment(tctx, "BATCH22: open with batch oplock\n");
2886 ZERO_STRUCT(break_info);
2887 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2888 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2889 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2890 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2891 NTCREATEX_SHARE_ACCESS_WRITE|
2892 NTCREATEX_SHARE_ACCESS_DELETE;
2893 status = smb_raw_open(cli1->tree, tctx, &io);
2894 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2895 fnum = io.ntcreatex.out.file.fnum;
2896 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2898 torture_comment(tctx, "a 2nd open should not succeed after the oplock "
2899 "break timeout\n");
2900 tv = timeval_current();
2901 smbcli_oplock_handler(cli1->transport, oplock_handler_timeout, cli1->tree);
2902 status = smb_raw_open(cli1->tree, tctx, &io);
2904 if (TARGET_IS_W2K3(tctx)) {
2905 /* 2k3 has an issue here. xp/win7 are ok. */
2906 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2907 } else {
2908 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2911 fnum2 = io.ntcreatex.out.file.fnum;
2913 torture_wait_for_oplock_break(tctx);
2914 te = (int)timeval_elapsed(&tv);
2917 * Some servers detect clients that let oplocks timeout, so this check
2918 * only shows a warning message instead failing the test to eliminate
2919 * failures from repeated runs of the test. This isn't ideal, but
2920 * it's better than not running the test at all.
2922 CHECK_RANGE(te, timeout - 1, timeout + 15);
2924 CHECK_VAL(break_info.count, 1);
2925 CHECK_VAL(break_info.fnum, fnum);
2926 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2927 CHECK_VAL(break_info.failures, 0);
2928 ZERO_STRUCT(break_info);
2930 torture_comment(tctx, "a 2nd open should succeed after the oplock "
2931 "release without break\n");
2932 tv = timeval_current();
2933 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2934 status = smb_raw_open(cli1->tree, tctx, &io);
2935 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2936 #if 0
2937 /* Samba 3.6.0 and above behave as Windows. */
2938 if (TARGET_IS_SAMBA3(tctx)) {
2939 /* samba3 doesn't grant additional oplocks to bad clients. */
2940 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
2941 } else {
2942 CHECK_VAL(io.ntcreatex.out.oplock_level,
2943 LEVEL_II_OPLOCK_RETURN);
2945 #else
2946 CHECK_VAL(io.ntcreatex.out.oplock_level,
2947 LEVEL_II_OPLOCK_RETURN);
2948 #endif
2949 torture_wait_for_oplock_break(tctx);
2950 te = (int)timeval_elapsed(&tv);
2951 /* it should come in without delay */
2952 CHECK_RANGE(te+1, 0, timeout);
2953 fnum3 = io.ntcreatex.out.file.fnum;
2955 CHECK_VAL(break_info.count, 0);
2957 smbcli_close(cli1->tree, fnum);
2958 smbcli_close(cli1->tree, fnum2);
2959 smbcli_close(cli1->tree, fnum3);
2961 done:
2962 smb_raw_exit(cli1->session);
2963 smb_raw_exit(cli2->session);
2964 smbcli_deltree(cli1->tree, BASEDIR);
2965 return ret;
2968 static bool test_raw_oplock_batch23(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2970 const char *fname = BASEDIR "\\test_batch23.dat";
2971 NTSTATUS status;
2972 bool ret = true;
2973 union smb_open io;
2974 uint16_t fnum=0, fnum2=0,fnum3=0;
2975 struct smbcli_state *cli3 = NULL;
2977 if (!torture_setup_dir(cli1, BASEDIR)) {
2978 return false;
2981 /* cleanup */
2982 smbcli_unlink(cli1->tree, fname);
2984 ret = open_connection_no_level2_oplocks(tctx, &cli3);
2985 CHECK_VAL(ret, true);
2987 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2988 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
2989 smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
2992 base ntcreatex parms
2994 io.generic.level = RAW_OPEN_NTCREATEX;
2995 io.ntcreatex.in.root_fid.fnum = 0;
2996 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2997 io.ntcreatex.in.alloc_size = 0;
2998 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2999 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3000 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3001 io.ntcreatex.in.create_options = 0;
3002 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3003 io.ntcreatex.in.security_flags = 0;
3004 io.ntcreatex.in.fname = fname;
3006 torture_comment(tctx, "BATCH23: a open and ask for a batch oplock\n");
3007 ZERO_STRUCT(break_info);
3009 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
3010 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
3011 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3012 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3013 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3014 status = smb_raw_open(cli1->tree, tctx, &io);
3015 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3016 fnum = io.ntcreatex.out.file.fnum;
3017 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3019 ZERO_STRUCT(break_info);
3021 torture_comment(tctx, "a 2nd open without level2 oplock support should generate a break to level2\n");
3022 status = smb_raw_open(cli3->tree, tctx, &io);
3023 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3024 fnum3 = io.ntcreatex.out.file.fnum;
3025 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
3027 torture_wait_for_oplock_break(tctx);
3028 CHECK_VAL(break_info.count, 1);
3029 CHECK_VAL(break_info.fnum, fnum);
3030 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3031 CHECK_VAL(break_info.failures, 0);
3033 ZERO_STRUCT(break_info);
3035 torture_comment(tctx, "a 3rd open with level2 oplock support should not generate a break\n");
3036 status = smb_raw_open(cli2->tree, tctx, &io);
3037 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3038 fnum2 = io.ntcreatex.out.file.fnum;
3039 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
3041 torture_wait_for_oplock_break(tctx);
3042 CHECK_VAL(break_info.count, 0);
3044 smbcli_close(cli1->tree, fnum);
3045 smbcli_close(cli2->tree, fnum2);
3046 smbcli_close(cli3->tree, fnum3);
3048 done:
3049 smb_raw_exit(cli1->session);
3050 smb_raw_exit(cli2->session);
3051 smb_raw_exit(cli3->session);
3052 smbcli_deltree(cli1->tree, BASEDIR);
3053 return ret;
3056 static bool test_raw_oplock_batch24(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
3058 const char *fname = BASEDIR "\\test_batch24.dat";
3059 NTSTATUS status;
3060 bool ret = true;
3061 union smb_open io;
3062 uint16_t fnum2=0,fnum3=0;
3063 struct smbcli_state *cli3 = NULL;
3065 if (!torture_setup_dir(cli1, BASEDIR)) {
3066 return false;
3069 /* cleanup */
3070 smbcli_unlink(cli1->tree, fname);
3072 ret = open_connection_no_level2_oplocks(tctx, &cli3);
3073 CHECK_VAL(ret, true);
3075 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3076 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
3077 smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
3080 base ntcreatex parms
3082 io.generic.level = RAW_OPEN_NTCREATEX;
3083 io.ntcreatex.in.root_fid.fnum = 0;
3084 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3085 io.ntcreatex.in.alloc_size = 0;
3086 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3087 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3088 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3089 io.ntcreatex.in.create_options = 0;
3090 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3091 io.ntcreatex.in.security_flags = 0;
3092 io.ntcreatex.in.fname = fname;
3094 torture_comment(tctx, "BATCH24: a open without level support and ask for a batch oplock\n");
3095 ZERO_STRUCT(break_info);
3097 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
3098 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
3099 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3100 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3101 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3102 status = smb_raw_open(cli3->tree, tctx, &io);
3103 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3104 fnum3 = io.ntcreatex.out.file.fnum;
3105 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3107 ZERO_STRUCT(break_info);
3109 torture_comment(tctx, "a 2nd open with level2 oplock support should generate a break to none\n");
3110 status = smb_raw_open(cli2->tree, tctx, &io);
3111 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3112 fnum2 = io.ntcreatex.out.file.fnum;
3113 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
3115 torture_wait_for_oplock_break(tctx);
3116 CHECK_VAL(break_info.count, 1);
3117 CHECK_VAL(break_info.fnum, fnum3);
3118 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
3119 CHECK_VAL(break_info.failures, 0);
3121 smbcli_close(cli3->tree, fnum3);
3122 smbcli_close(cli2->tree, fnum2);
3124 done:
3125 smb_raw_exit(cli1->session);
3126 smb_raw_exit(cli2->session);
3127 smb_raw_exit(cli3->session);
3128 smbcli_deltree(cli1->tree, BASEDIR);
3129 return ret;
3132 static bool test_raw_oplock_batch25(struct torture_context *tctx,
3133 struct smbcli_state *cli1,
3134 struct smbcli_state *cli2)
3136 const char *fname = BASEDIR "\\test_batch25.dat";
3137 NTSTATUS status;
3138 bool ret = true;
3139 union smb_open io;
3140 union smb_setfileinfo sfi;
3141 uint16_t fnum=0;
3143 if (!torture_setup_dir(cli1, BASEDIR)) {
3144 return false;
3147 /* cleanup */
3148 smbcli_unlink(cli1->tree, fname);
3150 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3153 base ntcreatex parms
3155 io.generic.level = RAW_OPEN_NTCREATEX;
3156 io.ntcreatex.in.root_fid.fnum = 0;
3157 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3158 io.ntcreatex.in.alloc_size = 0;
3159 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3160 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3161 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3162 io.ntcreatex.in.create_options = 0;
3163 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3164 io.ntcreatex.in.security_flags = 0;
3165 io.ntcreatex.in.fname = fname;
3167 torture_comment(tctx, "BATCH25: open a file with an batch oplock "
3168 "(share mode: none)\n");
3170 ZERO_STRUCT(break_info);
3171 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3172 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3173 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3174 status = smb_raw_open(cli1->tree, tctx, &io);
3175 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3176 fnum = io.ntcreatex.out.file.fnum;
3177 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3179 torture_comment(tctx, "setpathinfo attribute info should not trigger "
3180 "a break nor a violation\n");
3181 ZERO_STRUCT(sfi);
3182 sfi.generic.level = RAW_SFILEINFO_SETATTR;
3183 sfi.generic.in.file.path = fname;
3184 sfi.setattr.in.attrib = FILE_ATTRIBUTE_HIDDEN;
3185 sfi.setattr.in.write_time = 0;
3187 status = smb_raw_setpathinfo(cli2->tree, &sfi);
3188 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3190 torture_wait_for_oplock_break(tctx);
3191 CHECK_VAL(break_info.count, 0);
3193 smbcli_close(cli1->tree, fnum);
3195 done:
3196 smb_raw_exit(cli1->session);
3197 smb_raw_exit(cli2->session);
3198 smbcli_deltree(cli1->tree, BASEDIR);
3199 return ret;
3203 * Similar to batch17/18, but test with open share mode rather than
3204 * share_none.
3206 static bool test_raw_oplock_batch26(struct torture_context *tctx,
3207 struct smbcli_state *cli1, struct smbcli_state *cli2)
3209 const char *fname1 = BASEDIR "\\test_batch26_1.dat";
3210 const char *fname2 = BASEDIR "\\test_batch26_2.dat";
3211 NTSTATUS status;
3212 bool ret = true;
3213 union smb_open io;
3214 union smb_rename rn;
3215 uint16_t fnum=0;
3217 if (!torture_setup_dir(cli1, BASEDIR)) {
3218 return false;
3221 /* cleanup */
3222 smbcli_unlink(cli1->tree, fname1);
3223 smbcli_unlink(cli1->tree, fname2);
3225 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3226 cli1->tree);
3229 base ntcreatex parms
3231 io.generic.level = RAW_OPEN_NTCREATEX;
3232 io.ntcreatex.in.root_fid.fnum = 0;
3233 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3234 io.ntcreatex.in.alloc_size = 0;
3235 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3236 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3237 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
3238 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3239 io.ntcreatex.in.create_options = 0;
3240 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3241 io.ntcreatex.in.security_flags = 0;
3242 io.ntcreatex.in.fname = fname1;
3244 torture_comment(tctx, "BATCH26: open a file with an batch oplock "
3245 "(share mode: none)\n");
3247 ZERO_STRUCT(break_info);
3248 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3249 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3250 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3253 status = smb_raw_open(cli1->tree, tctx, &io);
3254 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3255 fnum = io.ntcreatex.out.file.fnum;
3256 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3258 torture_comment(tctx, "rename should trigger a break\n");
3259 ZERO_STRUCT(rn);
3260 rn.generic.level = RAW_RENAME_RENAME;
3261 rn.rename.in.pattern1 = fname1;
3262 rn.rename.in.pattern2 = fname2;
3263 rn.rename.in.attrib = 0;
3265 torture_comment(tctx, "trying rename while first file open\n");
3266 status = smb_raw_rename(cli2->tree, &rn);
3267 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
3269 torture_wait_for_oplock_break(tctx);
3270 CHECK_VAL(break_info.count, 1);
3271 CHECK_VAL(break_info.failures, 0);
3272 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3274 /* Close and reopen with batch again. */
3275 smbcli_close(cli1->tree, fnum);
3276 ZERO_STRUCT(break_info);
3278 status = smb_raw_open(cli1->tree, tctx, &io);
3279 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3280 fnum = io.ntcreatex.out.file.fnum;
3281 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3283 /* Now try ntrename. */
3284 torture_comment(tctx, "ntrename should trigger a break\n");
3285 ZERO_STRUCT(rn);
3286 rn.generic.level = RAW_RENAME_NTRENAME;
3287 rn.ntrename.in.attrib = 0;
3288 rn.ntrename.in.flags = RENAME_FLAG_RENAME;
3289 rn.ntrename.in.old_name = fname1;
3290 rn.ntrename.in.new_name = fname2;
3291 torture_comment(tctx, "trying rename while first file open\n");
3292 status = smb_raw_rename(cli2->tree, &rn);
3293 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
3295 torture_wait_for_oplock_break(tctx);
3296 CHECK_VAL(break_info.count, 1);
3297 CHECK_VAL(break_info.failures, 0);
3298 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3300 smbcli_close(cli1->tree, fnum);
3302 done:
3303 smb_raw_exit(cli1->session);
3304 smb_raw_exit(cli2->session);
3305 smbcli_deltree(cli1->tree, BASEDIR);
3306 return ret;
3309 /* Test how oplocks work on streams. */
3310 static bool test_raw_oplock_stream1(struct torture_context *tctx,
3311 struct smbcli_state *cli1,
3312 struct smbcli_state *cli2)
3314 NTSTATUS status;
3315 union smb_open io;
3316 const char *fname_base = BASEDIR "\\test_stream1.txt";
3317 const char *stream = "Stream One:$DATA";
3318 const char *fname_stream, *fname_default_stream;
3319 const char *default_stream = "::$DATA";
3320 bool ret = true;
3321 int fnum = -1;
3322 int i;
3323 int stream_fnum = -1;
3324 uint32_t batch_req = NTCREATEX_FLAGS_REQUEST_OPLOCK |
3325 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK | NTCREATEX_FLAGS_EXTENDED;
3326 uint32_t exclusive_req = NTCREATEX_FLAGS_REQUEST_OPLOCK |
3327 NTCREATEX_FLAGS_EXTENDED;
3329 #define NSTREAM_OPLOCK_RESULTS 8
3330 struct {
3331 const char **fname;
3332 bool open_base_file;
3333 uint32_t oplock_req;
3334 uint32_t oplock_granted;
3335 } stream_oplock_results[NSTREAM_OPLOCK_RESULTS] = {
3336 /* Request oplock on stream without the base file open. */
3337 {&fname_stream, false, batch_req, NO_OPLOCK_RETURN},
3338 {&fname_default_stream, false, batch_req, NO_OPLOCK_RETURN},
3339 {&fname_stream, false, exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
3340 {&fname_default_stream, false, exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
3342 /* Request oplock on stream with the base file open. */
3343 {&fname_stream, true, batch_req, NO_OPLOCK_RETURN},
3344 {&fname_default_stream, true, batch_req, NO_OPLOCK_RETURN},
3345 {&fname_stream, true, exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
3346 {&fname_default_stream, true, exclusive_req, LEVEL_II_OPLOCK_RETURN},
3351 /* Only passes against windows at the moment. */
3352 if (torture_setting_bool(tctx, "samba3", false) ||
3353 torture_setting_bool(tctx, "samba4", false)) {
3354 torture_skip(tctx, "STREAM1 disabled against samba3+4\n");
3357 fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
3358 fname_default_stream = talloc_asprintf(tctx, "%s%s", fname_base,
3359 default_stream);
3361 if (!torture_setup_dir(cli1, BASEDIR)) {
3362 return false;
3364 smbcli_unlink(cli1->tree, fname_base);
3366 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
3367 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
3369 /* Setup generic open parameters. */
3370 io.generic.level = RAW_OPEN_NTCREATEX;
3371 io.ntcreatex.in.root_fid.fnum = 0;
3372 io.ntcreatex.in.access_mask = (SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA|
3373 SEC_FILE_APPEND_DATA|SEC_STD_READ_CONTROL);
3374 io.ntcreatex.in.create_options = 0;
3375 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3376 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3377 NTCREATEX_SHARE_ACCESS_WRITE;
3378 io.ntcreatex.in.alloc_size = 0;
3379 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3380 io.ntcreatex.in.security_flags = 0;
3382 /* Create the file with a stream */
3383 io.ntcreatex.in.fname = fname_stream;
3384 io.ntcreatex.in.flags = 0;
3385 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
3386 status = smb_raw_open(cli1->tree, tctx, &io);
3387 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3388 smbcli_close(cli1->tree, io.ntcreatex.out.file.fnum);
3390 /* Change the disposition to open now that the file has been created. */
3391 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
3393 /* Try some permutations of taking oplocks on streams. */
3394 for (i = 0; i < NSTREAM_OPLOCK_RESULTS; i++) {
3395 const char *fname = *stream_oplock_results[i].fname;
3396 bool open_base_file = stream_oplock_results[i].open_base_file;
3397 uint32_t oplock_req = stream_oplock_results[i].oplock_req;
3398 uint32_t oplock_granted =
3399 stream_oplock_results[i].oplock_granted;
3400 int base_fnum = -1;
3402 if (open_base_file) {
3403 torture_comment(tctx, "Opening base file: %s with "
3404 "%d\n", fname_base, batch_req);
3405 io.ntcreatex.in.fname = fname_base;
3406 io.ntcreatex.in.flags = batch_req;
3407 status = smb_raw_open(cli2->tree, tctx, &io);
3408 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3409 CHECK_VAL(io.ntcreatex.out.oplock_level,
3410 BATCH_OPLOCK_RETURN);
3411 base_fnum = io.ntcreatex.out.file.fnum;
3414 torture_comment(tctx, "%d: Opening stream: %s with %d\n", i,
3415 fname, oplock_req);
3416 io.ntcreatex.in.fname = fname;
3417 io.ntcreatex.in.flags = oplock_req;
3419 /* Do the open with the desired oplock on the stream. */
3420 status = smb_raw_open(cli1->tree, tctx, &io);
3421 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3422 CHECK_VAL(io.ntcreatex.out.oplock_level, oplock_granted);
3423 smbcli_close(cli1->tree, io.ntcreatex.out.file.fnum);
3425 /* Cleanup the base file if it was opened. */
3426 if (base_fnum != -1) {
3427 smbcli_close(cli2->tree, base_fnum);
3431 /* Open the stream with an exclusive oplock. */
3432 torture_comment(tctx, "Opening stream: %s with %d\n",
3433 fname_stream, exclusive_req);
3434 io.ntcreatex.in.fname = fname_stream;
3435 io.ntcreatex.in.flags = exclusive_req;
3436 status = smb_raw_open(cli1->tree, tctx, &io);
3437 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3438 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
3439 stream_fnum = io.ntcreatex.out.file.fnum;
3441 /* Open the base file and see if it contends. */
3442 ZERO_STRUCT(break_info);
3443 torture_comment(tctx, "Opening base file: %s with "
3444 "%d\n", fname_base, batch_req);
3445 io.ntcreatex.in.fname = fname_base;
3446 io.ntcreatex.in.flags = batch_req;
3447 status = smb_raw_open(cli2->tree, tctx, &io);
3448 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3449 CHECK_VAL(io.ntcreatex.out.oplock_level,
3450 BATCH_OPLOCK_RETURN);
3451 smbcli_close(cli2->tree, io.ntcreatex.out.file.fnum);
3453 torture_wait_for_oplock_break(tctx);
3454 CHECK_VAL(break_info.count, 0);
3455 CHECK_VAL(break_info.failures, 0);
3457 /* Open the stream again to see if it contends. */
3458 ZERO_STRUCT(break_info);
3459 torture_comment(tctx, "Opening stream again: %s with "
3460 "%d\n", fname_base, batch_req);
3461 io.ntcreatex.in.fname = fname_stream;
3462 io.ntcreatex.in.flags = exclusive_req;
3463 status = smb_raw_open(cli2->tree, tctx, &io);
3464 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3465 CHECK_VAL(io.ntcreatex.out.oplock_level,
3466 LEVEL_II_OPLOCK_RETURN);
3467 smbcli_close(cli2->tree, io.ntcreatex.out.file.fnum);
3469 torture_wait_for_oplock_break(tctx);
3470 CHECK_VAL(break_info.count, 1);
3471 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3472 CHECK_VAL(break_info.failures, 0);
3474 /* Close the stream. */
3475 if (stream_fnum != -1) {
3476 smbcli_close(cli1->tree, stream_fnum);
3479 done:
3480 smbcli_close(cli1->tree, fnum);
3481 smb_raw_exit(cli1->session);
3482 smb_raw_exit(cli2->session);
3483 smbcli_deltree(cli1->tree, BASEDIR);
3484 return ret;
3487 static bool test_raw_oplock_doc(struct torture_context *tctx,
3488 struct smbcli_state *cli)
3490 const char *fname = BASEDIR "\\test_oplock_doc.dat";
3491 NTSTATUS status;
3492 bool ret = true;
3493 union smb_open io;
3494 uint16_t fnum=0;
3496 if (!torture_setup_dir(cli, BASEDIR)) {
3497 return false;
3500 /* cleanup */
3501 smbcli_unlink(cli->tree, fname);
3503 smbcli_oplock_handler(cli->transport, oplock_handler_ack_to_given,
3504 cli->tree);
3507 base ntcreatex parms
3509 io.generic.level = RAW_OPEN_NTCREATEX;
3510 io.ntcreatex.in.root_fid.fnum = 0;
3511 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3512 io.ntcreatex.in.alloc_size = 0;
3513 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3514 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3515 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3516 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
3517 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3518 io.ntcreatex.in.security_flags = 0;
3519 io.ntcreatex.in.fname = fname;
3521 torture_comment(tctx, "open a delete-on-close file with a batch "
3522 "oplock\n");
3523 ZERO_STRUCT(break_info);
3524 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3525 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3526 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3528 status = smb_raw_open(cli->tree, tctx, &io);
3529 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3530 fnum = io.ntcreatex.out.file.fnum;
3531 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3533 smbcli_close(cli->tree, fnum);
3535 done:
3536 smb_raw_exit(cli->session);
3537 smbcli_deltree(cli->tree, BASEDIR);
3538 return ret;
3541 /* Open a file with a batch oplock, then open it again from a second client
3542 * requesting no oplock. Having two open file handles should break our own
3543 * oplock during BRL acquisition.
3545 static bool test_raw_oplock_brl1(struct torture_context *tctx,
3546 struct smbcli_state *cli1,
3547 struct smbcli_state *cli2)
3549 const char *fname = BASEDIR "\\test_batch_brl.dat";
3550 /*int fname, f;*/
3551 bool ret = true;
3552 uint8_t buf[1000];
3553 union smb_open io;
3554 NTSTATUS status;
3555 uint16_t fnum=0;
3556 uint16_t fnum2=0;
3558 if (!torture_setup_dir(cli1, BASEDIR)) {
3559 return false;
3562 /* cleanup */
3563 smbcli_unlink(cli1->tree, fname);
3565 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3566 cli1->tree);
3569 base ntcreatex parms
3571 io.generic.level = RAW_OPEN_NTCREATEX;
3572 io.ntcreatex.in.root_fid.fnum = 0;
3573 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3574 SEC_RIGHTS_FILE_WRITE;
3575 io.ntcreatex.in.alloc_size = 0;
3576 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3577 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3578 NTCREATEX_SHARE_ACCESS_WRITE;
3579 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3580 io.ntcreatex.in.create_options = 0;
3581 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3582 io.ntcreatex.in.security_flags = 0;
3583 io.ntcreatex.in.fname = fname;
3586 with a batch oplock we get a break
3588 torture_comment(tctx, "open with batch oplock\n");
3589 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3590 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3591 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3593 status = smb_raw_open(cli1->tree, tctx, &io);
3594 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3595 fnum = io.ntcreatex.out.file.fnum;
3596 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3597 /* create a file with bogus data */
3598 memset(buf, 0, sizeof(buf));
3600 if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
3601 sizeof(buf))
3603 torture_comment(tctx, "Failed to create file\n");
3604 goto done;
3607 torture_comment(tctx, "a 2nd open should give a break\n");
3608 ZERO_STRUCT(break_info);
3610 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
3611 status = smb_raw_open(cli2->tree, tctx, &io);
3612 fnum2 = io.ntcreatex.out.file.fnum;
3613 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3614 CHECK_VAL(break_info.count, 1);
3615 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3616 CHECK_VAL(break_info.failures, 0);
3617 CHECK_VAL(break_info.fnum, fnum);
3619 ZERO_STRUCT(break_info);
3621 torture_comment(tctx, "a self BRL acquisition should break to none\n");
3623 status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
3624 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3626 torture_wait_for_oplock_break(tctx);
3627 CHECK_VAL(break_info.count, 1);
3628 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
3629 CHECK_VAL(break_info.fnum, fnum);
3630 CHECK_VAL(break_info.failures, 0);
3632 /* expect no oplock break */
3633 ZERO_STRUCT(break_info);
3634 status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
3635 CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
3637 torture_wait_for_oplock_break(tctx);
3638 CHECK_VAL(break_info.count, 0);
3639 CHECK_VAL(break_info.level, 0);
3640 CHECK_VAL(break_info.fnum, 0);
3641 CHECK_VAL(break_info.failures, 0);
3643 smbcli_close(cli1->tree, fnum);
3644 smbcli_close(cli2->tree, fnum2);
3646 done:
3647 smb_raw_exit(cli1->session);
3648 smb_raw_exit(cli2->session);
3649 smbcli_deltree(cli1->tree, BASEDIR);
3650 return ret;
3654 /* Open a file with a batch oplock on one client and then acquire a brl.
3655 * We should not contend our own oplock.
3657 static bool test_raw_oplock_brl2(struct torture_context *tctx, struct smbcli_state *cli1)
3659 const char *fname = BASEDIR "\\test_batch_brl.dat";
3660 /*int fname, f;*/
3661 bool ret = true;
3662 uint8_t buf[1000];
3663 union smb_open io;
3664 NTSTATUS status;
3665 uint16_t fnum=0;
3667 if (!torture_setup_dir(cli1, BASEDIR)) {
3668 return false;
3671 /* cleanup */
3672 smbcli_unlink(cli1->tree, fname);
3674 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3675 cli1->tree);
3678 base ntcreatex parms
3680 io.generic.level = RAW_OPEN_NTCREATEX;
3681 io.ntcreatex.in.root_fid.fnum = 0;
3682 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3683 SEC_RIGHTS_FILE_WRITE;
3684 io.ntcreatex.in.alloc_size = 0;
3685 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3686 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3687 NTCREATEX_SHARE_ACCESS_WRITE;
3688 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3689 io.ntcreatex.in.create_options = 0;
3690 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3691 io.ntcreatex.in.security_flags = 0;
3692 io.ntcreatex.in.fname = fname;
3695 with a batch oplock we get a break
3697 torture_comment(tctx, "open with batch oplock\n");
3698 ZERO_STRUCT(break_info);
3699 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3700 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3701 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3703 status = smb_raw_open(cli1->tree, tctx, &io);
3704 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3705 fnum = io.ntcreatex.out.file.fnum;
3706 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3708 /* create a file with bogus data */
3709 memset(buf, 0, sizeof(buf));
3711 if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
3712 sizeof(buf))
3714 torture_comment(tctx, "Failed to create file\n");
3715 goto done;
3718 torture_comment(tctx, "a self BRL acquisition should not break to "
3719 "none\n");
3721 status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
3722 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3724 status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
3725 CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
3727 /* With one file handle open a BRL should not contend our oplock.
3728 * Thus, no oplock break will be received and the entire break_info
3729 * struct will be 0 */
3730 torture_wait_for_oplock_break(tctx);
3731 CHECK_VAL(break_info.fnum, 0);
3732 CHECK_VAL(break_info.count, 0);
3733 CHECK_VAL(break_info.level, 0);
3734 CHECK_VAL(break_info.failures, 0);
3736 smbcli_close(cli1->tree, fnum);
3738 done:
3739 smb_raw_exit(cli1->session);
3740 smbcli_deltree(cli1->tree, BASEDIR);
3741 return ret;
3744 /* Open a file with a batch oplock twice from one client and then acquire a
3745 * brl. BRL acquisition should break our own oplock.
3747 static bool test_raw_oplock_brl3(struct torture_context *tctx,
3748 struct smbcli_state *cli1)
3750 const char *fname = BASEDIR "\\test_batch_brl.dat";
3751 bool ret = true;
3752 uint8_t buf[1000];
3753 bool correct = true;
3754 union smb_open io;
3755 NTSTATUS status;
3756 uint16_t fnum=0;
3757 uint16_t fnum2=0;
3759 if (!torture_setup_dir(cli1, BASEDIR)) {
3760 return false;
3763 /* cleanup */
3764 smbcli_unlink(cli1->tree, fname);
3766 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3767 cli1->tree);
3770 base ntcreatex parms
3772 io.generic.level = RAW_OPEN_NTCREATEX;
3773 io.ntcreatex.in.root_fid.fnum = 0;
3774 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3775 SEC_RIGHTS_FILE_WRITE;
3776 io.ntcreatex.in.alloc_size = 0;
3777 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3778 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3779 NTCREATEX_SHARE_ACCESS_WRITE;
3780 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3781 io.ntcreatex.in.create_options = 0;
3782 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3783 io.ntcreatex.in.security_flags = 0;
3784 io.ntcreatex.in.fname = fname;
3787 with a batch oplock we get a break
3789 torture_comment(tctx, "open with batch oplock\n");
3790 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3791 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3792 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3794 status = smb_raw_open(cli1->tree, tctx, &io);
3795 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3796 fnum = io.ntcreatex.out.file.fnum;
3797 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3799 /* create a file with bogus data */
3800 memset(buf, 0, sizeof(buf));
3802 if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
3803 sizeof(buf))
3805 torture_comment(tctx, "Failed to create file\n");
3806 correct = false;
3807 goto done;
3810 torture_comment(tctx, "a 2nd open should give a break\n");
3811 ZERO_STRUCT(break_info);
3813 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
3814 status = smb_raw_open(cli1->tree, tctx, &io);
3815 fnum2 = io.ntcreatex.out.file.fnum;
3816 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3817 CHECK_VAL(break_info.count, 1);
3818 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3819 CHECK_VAL(break_info.failures, 0);
3820 CHECK_VAL(break_info.fnum, fnum);
3822 ZERO_STRUCT(break_info);
3824 torture_comment(tctx, "a self BRL acquisition should break to none\n");
3826 status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
3827 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3829 torture_wait_for_oplock_break(tctx);
3830 CHECK_VAL(break_info.count, 1);
3831 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
3832 CHECK_VAL(break_info.fnum, fnum);
3833 CHECK_VAL(break_info.failures, 0);
3835 /* expect no oplock break */
3836 ZERO_STRUCT(break_info);
3837 status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
3838 CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
3840 torture_wait_for_oplock_break(tctx);
3841 CHECK_VAL(break_info.count, 0);
3842 CHECK_VAL(break_info.level, 0);
3843 CHECK_VAL(break_info.fnum, 0);
3844 CHECK_VAL(break_info.failures, 0);
3846 smbcli_close(cli1->tree, fnum);
3847 smbcli_close(cli1->tree, fnum2);
3849 done:
3850 smb_raw_exit(cli1->session);
3851 smbcli_deltree(cli1->tree, BASEDIR);
3852 return ret;
3856 * Open a file with an exclusive oplock from the 1st client and acquire a
3857 * brl. Then open the same file from the 2nd client that should give oplock
3858 * break with level2 to the 1st and return no oplock to the 2nd.
3860 static bool test_raw_oplock_brl4(struct torture_context *tctx,
3861 struct smbcli_state *cli1,
3862 struct smbcli_state *cli2)
3864 const char *fname = BASEDIR "\\test_batch_brl.dat";
3865 bool ret = true;
3866 uint8_t buf[1000];
3867 union smb_open io;
3868 NTSTATUS status;
3869 uint16_t fnum = 0;
3870 uint16_t fnum2 = 0;
3872 if (!torture_setup_dir(cli1, BASEDIR)) {
3873 return false;
3876 /* cleanup */
3877 smbcli_unlink(cli1->tree, fname);
3879 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3880 cli1->tree);
3883 base ntcreatex parms
3885 io.generic.level = RAW_OPEN_NTCREATEX;
3886 io.ntcreatex.in.root_fid.fnum = 0;
3887 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3888 SEC_RIGHTS_FILE_WRITE;
3889 io.ntcreatex.in.alloc_size = 0;
3890 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3891 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3892 NTCREATEX_SHARE_ACCESS_WRITE;
3893 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3894 io.ntcreatex.in.create_options = 0;
3895 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3896 io.ntcreatex.in.security_flags = 0;
3897 io.ntcreatex.in.fname = fname;
3899 torture_comment(tctx, "open with exclusive oplock\n");
3900 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3901 NTCREATEX_FLAGS_REQUEST_OPLOCK;
3903 status = smb_raw_open(cli1->tree, tctx, &io);
3905 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3906 fnum = io.ntcreatex.out.file.fnum;
3907 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
3909 /* create a file with bogus data */
3910 memset(buf, 0, sizeof(buf));
3912 if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
3913 sizeof(buf))
3915 torture_comment(tctx, "Failed to create file\n");
3916 goto done;
3919 status = smbcli_lock(cli1->tree, fnum, 0, 1, 0, WRITE_LOCK);
3920 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3922 torture_comment(tctx, "a 2nd open should give a break to the 1st\n");
3923 ZERO_STRUCT(break_info);
3925 status = smb_raw_open(cli2->tree, tctx, &io);
3927 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3928 CHECK_VAL(break_info.count, 1);
3929 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3930 CHECK_VAL(break_info.failures, 0);
3931 CHECK_VAL(break_info.fnum, fnum);
3933 torture_comment(tctx, "and return no oplock to the 2nd\n");
3934 fnum2 = io.ntcreatex.out.file.fnum;
3935 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
3937 smbcli_close(cli1->tree, fnum);
3938 smbcli_close(cli2->tree, fnum2);
3940 done:
3941 smb_raw_exit(cli1->session);
3942 smb_raw_exit(cli2->session);
3943 smbcli_deltree(cli1->tree, BASEDIR);
3944 return ret;
3948 basic testing of oplocks
3950 struct torture_suite *torture_raw_oplock(TALLOC_CTX *mem_ctx)
3952 struct torture_suite *suite = torture_suite_create(mem_ctx, "oplock");
3954 torture_suite_add_2smb_test(suite, "exclusive1", test_raw_oplock_exclusive1);
3955 torture_suite_add_2smb_test(suite, "exclusive2", test_raw_oplock_exclusive2);
3956 torture_suite_add_2smb_test(suite, "exclusive3", test_raw_oplock_exclusive3);
3957 torture_suite_add_2smb_test(suite, "exclusive4", test_raw_oplock_exclusive4);
3958 torture_suite_add_2smb_test(suite, "exclusive5", test_raw_oplock_exclusive5);
3959 torture_suite_add_2smb_test(suite, "exclusive6", test_raw_oplock_exclusive6);
3960 torture_suite_add_2smb_test(suite, "exclusive7", test_raw_oplock_exclusive7);
3961 torture_suite_add_2smb_test(suite, "batch1", test_raw_oplock_batch1);
3962 torture_suite_add_2smb_test(suite, "batch2", test_raw_oplock_batch2);
3963 torture_suite_add_2smb_test(suite, "batch3", test_raw_oplock_batch3);
3964 torture_suite_add_2smb_test(suite, "batch4", test_raw_oplock_batch4);
3965 torture_suite_add_2smb_test(suite, "batch5", test_raw_oplock_batch5);
3966 torture_suite_add_2smb_test(suite, "batch6", test_raw_oplock_batch6);
3967 torture_suite_add_2smb_test(suite, "batch7", test_raw_oplock_batch7);
3968 torture_suite_add_2smb_test(suite, "batch8", test_raw_oplock_batch8);
3969 torture_suite_add_2smb_test(suite, "batch9", test_raw_oplock_batch9);
3970 torture_suite_add_2smb_test(suite, "batch10", test_raw_oplock_batch10);
3971 torture_suite_add_2smb_test(suite, "batch11", test_raw_oplock_batch11);
3972 torture_suite_add_2smb_test(suite, "batch12", test_raw_oplock_batch12);
3973 torture_suite_add_2smb_test(suite, "batch13", test_raw_oplock_batch13);
3974 torture_suite_add_2smb_test(suite, "batch14", test_raw_oplock_batch14);
3975 torture_suite_add_2smb_test(suite, "batch15", test_raw_oplock_batch15);
3976 torture_suite_add_2smb_test(suite, "batch16", test_raw_oplock_batch16);
3977 torture_suite_add_2smb_test(suite, "batch17", test_raw_oplock_batch17);
3978 torture_suite_add_2smb_test(suite, "batch18", test_raw_oplock_batch18);
3979 torture_suite_add_2smb_test(suite, "batch19", test_raw_oplock_batch19);
3980 torture_suite_add_2smb_test(suite, "batch20", test_raw_oplock_batch20);
3981 torture_suite_add_2smb_test(suite, "batch21", test_raw_oplock_batch21);
3982 torture_suite_add_2smb_test(suite, "batch22", test_raw_oplock_batch22);
3983 torture_suite_add_2smb_test(suite, "batch23", test_raw_oplock_batch23);
3984 torture_suite_add_2smb_test(suite, "batch24", test_raw_oplock_batch24);
3985 torture_suite_add_2smb_test(suite, "batch25", test_raw_oplock_batch25);
3986 torture_suite_add_2smb_test(suite, "batch26", test_raw_oplock_batch26);
3987 torture_suite_add_2smb_test(suite, "stream1", test_raw_oplock_stream1);
3988 torture_suite_add_1smb_test(suite, "doc1", test_raw_oplock_doc);
3989 torture_suite_add_2smb_test(suite, "brl1", test_raw_oplock_brl1);
3990 torture_suite_add_1smb_test(suite, "brl2", test_raw_oplock_brl2);
3991 torture_suite_add_1smb_test(suite, "brl3", test_raw_oplock_brl3);
3992 torture_suite_add_2smb_test(suite, "brl4", test_raw_oplock_brl4);
3994 return suite;
3998 stress testing of oplocks
4000 bool torture_bench_oplock(struct torture_context *torture)
4002 struct smbcli_state **cli;
4003 bool ret = true;
4004 TALLOC_CTX *mem_ctx = talloc_new(torture);
4005 int torture_nprocs = torture_setting_int(torture, "nprocs", 4);
4006 int i, count=0;
4007 int timelimit = torture_setting_int(torture, "timelimit", 10);
4008 union smb_open io;
4009 struct timeval tv;
4011 cli = talloc_array(mem_ctx, struct smbcli_state *, torture_nprocs);
4013 torture_comment(torture, "Opening %d connections\n", torture_nprocs);
4014 for (i=0;i<torture_nprocs;i++) {
4015 if (!torture_open_connection_ev(&cli[i], i, torture, torture->ev)) {
4016 return false;
4018 talloc_steal(mem_ctx, cli[i]);
4019 smbcli_oplock_handler(cli[i]->transport, oplock_handler_close,
4020 cli[i]->tree);
4023 if (!torture_setup_dir(cli[0], BASEDIR)) {
4024 ret = false;
4025 goto done;
4028 io.ntcreatex.level = RAW_OPEN_NTCREATEX;
4029 io.ntcreatex.in.root_fid.fnum = 0;
4030 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
4031 io.ntcreatex.in.alloc_size = 0;
4032 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
4033 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
4034 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
4035 io.ntcreatex.in.create_options = 0;
4036 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
4037 io.ntcreatex.in.security_flags = 0;
4038 io.ntcreatex.in.fname = BASEDIR "\\test.dat";
4039 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
4040 NTCREATEX_FLAGS_REQUEST_OPLOCK |
4041 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
4043 tv = timeval_current();
4046 we open the same file with SHARE_ACCESS_NONE from all the
4047 connections in a round robin fashion. Each open causes an
4048 oplock break on the previous connection, which is answered
4049 by the oplock_handler_close() to close the file.
4051 This measures how fast we can pass on oplocks, and stresses
4052 the oplock handling code
4054 torture_comment(torture, "Running for %d seconds\n", timelimit);
4055 while (timeval_elapsed(&tv) < timelimit) {
4056 for (i=0;i<torture_nprocs;i++) {
4057 NTSTATUS status;
4059 status = smb_raw_open(cli[i]->tree, mem_ctx, &io);
4060 CHECK_STATUS(torture, status, NT_STATUS_OK);
4061 count++;
4064 if (torture_setting_bool(torture, "progress", true)) {
4065 torture_comment(torture, "%.2f ops/second\r", count/timeval_elapsed(&tv));
4069 torture_comment(torture, "%.2f ops/second\n", count/timeval_elapsed(&tv));
4071 smb_raw_exit(cli[torture_nprocs-1]->session);
4073 done:
4074 smb_raw_exit(cli[0]->session);
4075 smbcli_deltree(cli[0]->tree, BASEDIR);
4076 talloc_free(mem_ctx);
4077 return ret;
4081 static struct hold_oplock_info {
4082 const char *fname;
4083 bool close_on_break;
4084 uint32_t share_access;
4085 uint16_t fnum;
4086 } hold_info[] = {
4087 { BASEDIR "\\notshared_close", true,
4088 NTCREATEX_SHARE_ACCESS_NONE, },
4089 { BASEDIR "\\notshared_noclose", false,
4090 NTCREATEX_SHARE_ACCESS_NONE, },
4091 { BASEDIR "\\shared_close", true,
4092 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
4093 { BASEDIR "\\shared_noclose", false,
4094 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
4097 static bool oplock_handler_hold(struct smbcli_transport *transport,
4098 uint16_t tid, uint16_t fnum, uint8_t level,
4099 void *private_data)
4101 struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
4102 struct hold_oplock_info *info;
4103 int i;
4105 for (i=0;i<ARRAY_SIZE(hold_info);i++) {
4106 if (hold_info[i].fnum == fnum) break;
4109 if (i == ARRAY_SIZE(hold_info)) {
4110 printf("oplock break for unknown fnum %u\n", fnum);
4111 return false;
4114 info = &hold_info[i];
4116 if (info->close_on_break) {
4117 printf("oplock break on %s - closing\n",
4118 info->fname);
4119 oplock_handler_close(transport, tid, fnum, level, private_data);
4120 return true;
4123 printf("oplock break on %s - acking break\n", info->fname);
4125 return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
4130 used for manual testing of oplocks - especially interaction with
4131 other filesystems (such as NFS and local access)
4133 bool torture_hold_oplock(struct torture_context *torture,
4134 struct smbcli_state *cli)
4136 struct tevent_context *ev =
4137 (struct tevent_context *)cli->transport->socket->event.ctx;
4138 int i;
4140 printf("Setting up open files with oplocks in %s\n", BASEDIR);
4142 if (!torture_setup_dir(cli, BASEDIR)) {
4143 return false;
4146 smbcli_oplock_handler(cli->transport, oplock_handler_hold, cli->tree);
4148 /* setup the files */
4149 for (i=0;i<ARRAY_SIZE(hold_info);i++) {
4150 union smb_open io;
4151 NTSTATUS status;
4152 char c = 1;
4154 io.generic.level = RAW_OPEN_NTCREATEX;
4155 io.ntcreatex.in.root_fid.fnum = 0;
4156 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
4157 io.ntcreatex.in.alloc_size = 0;
4158 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
4159 io.ntcreatex.in.share_access = hold_info[i].share_access;
4160 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
4161 io.ntcreatex.in.create_options = 0;
4162 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
4163 io.ntcreatex.in.security_flags = 0;
4164 io.ntcreatex.in.fname = hold_info[i].fname;
4165 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
4166 NTCREATEX_FLAGS_REQUEST_OPLOCK |
4167 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
4168 printf("opening %s\n", hold_info[i].fname);
4170 status = smb_raw_open(cli->tree, cli, &io);
4171 if (!NT_STATUS_IS_OK(status)) {
4172 printf("Failed to open %s - %s\n",
4173 hold_info[i].fname, nt_errstr(status));
4174 return false;
4177 if (io.ntcreatex.out.oplock_level != BATCH_OPLOCK_RETURN) {
4178 printf("Oplock not granted for %s - expected %d but got %d\n",
4179 hold_info[i].fname, BATCH_OPLOCK_RETURN,
4180 io.ntcreatex.out.oplock_level);
4181 return false;
4183 hold_info[i].fnum = io.ntcreatex.out.file.fnum;
4185 /* make the file non-zero size */
4186 if (smbcli_write(cli->tree, hold_info[i].fnum, 0, &c, 0, 1) != 1) {
4187 printf("Failed to write to file\n");
4188 return false;
4192 printf("Waiting for oplock events\n");
4193 tevent_loop_wait(ev);
4195 return true;