s4/torture: don't mix declarations and code
[Samba/aatanasov.git] / source4 / torture / raw / oplock.c
blob1eaa7e214b4b9b78b89ee738ed8bc9fc2ce30d57
1 /*
2 Unix SMB/CIFS implementation.
3 basic raw test suite for oplocks
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "torture/torture.h"
22 #include "torture/smbtorture.h"
23 #include "librpc/gen_ndr/security.h"
24 #include "librpc/gen_ndr/ndr_security.h"
25 #include "libcli/raw/libcliraw.h"
26 #include "libcli/raw/raw_proto.h"
27 #include "libcli/security/security.h"
28 #include "libcli/libcli.h"
29 #include "torture/util.h"
30 #include "lib/events/events.h"
31 #include "param/param.h"
32 #include "lib/cmdline/popt_common.h"
33 #include "libcli/resolve/resolve.h"
35 #define CHECK_VAL(v, correct) do { \
36 if ((v) != (correct)) { \
37 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
38 __location__, #v, (int)v, (int)correct); \
39 ret = false; \
40 }} while (0)
42 #define CHECK_RANGE(v, min, max) do { \
43 if ((v) < (min) || (v) > (max)) { \
44 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got %d - should be between %d and %d\n", \
45 __location__, #v, (int)v, (int)min, (int)max); \
46 ret = false; \
47 }} while (0)
49 #define CHECK_STRMATCH(v, correct) do { \
50 if (!v || strstr((v),(correct)) == NULL) { \
51 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got '%s' - should be '%s'\n", \
52 __location__, #v, v?v:"NULL", correct); \
53 ret = false; \
54 } \
55 } while (0)
57 #define CHECK_STATUS(tctx, status, correct) do { \
58 if (!NT_STATUS_EQUAL(status, correct)) { \
59 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
60 nt_errstr(status), nt_errstr(correct)); \
61 ret = false; \
62 goto done; \
63 }} while (0)
66 static struct {
67 int fnum;
68 uint8_t level;
69 int count;
70 int failures;
71 } break_info;
73 #define BASEDIR "\\test_oplock"
76 a handler function for oplock break requests. Ack it as a break to level II if possible
78 static bool oplock_handler_ack_to_given(struct smbcli_transport *transport,
79 uint16_t tid, uint16_t fnum,
80 uint8_t level, void *private_data)
82 struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
83 const char *name;
85 break_info.fnum = fnum;
86 break_info.level = level;
87 break_info.count++;
89 switch (level) {
90 case OPLOCK_BREAK_TO_LEVEL_II:
91 name = "level II";
92 break;
93 case OPLOCK_BREAK_TO_NONE:
94 name = "none";
95 break;
96 default:
97 name = "unknown";
98 break_info.failures++;
100 printf("Acking to %s [0x%02X] in oplock handler\n",
101 name, level);
103 return smbcli_oplock_ack(tree, fnum, level);
107 a handler function for oplock break requests. Ack it as a break to none
109 static bool oplock_handler_ack_to_none(struct smbcli_transport *transport,
110 uint16_t tid, uint16_t fnum,
111 uint8_t level, void *private_data)
113 struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
114 break_info.fnum = fnum;
115 break_info.level = level;
116 break_info.count++;
118 printf("Acking to none in oplock handler\n");
120 return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
124 a handler function for oplock break requests. Let it timeout
126 static bool oplock_handler_timeout(struct smbcli_transport *transport,
127 uint16_t tid, uint16_t fnum,
128 uint8_t level, void *private_data)
130 break_info.fnum = fnum;
131 break_info.level = level;
132 break_info.count++;
134 printf("Let oplock break timeout\n");
135 return true;
138 static void oplock_handler_close_recv(struct smbcli_request *req)
140 NTSTATUS status;
141 status = smbcli_request_simple_recv(req);
142 if (!NT_STATUS_IS_OK(status)) {
143 printf("close failed in oplock_handler_close\n");
144 break_info.failures++;
149 a handler function for oplock break requests - close the file
151 static bool oplock_handler_close(struct smbcli_transport *transport, uint16_t tid,
152 uint16_t fnum, uint8_t level, void *private_data)
154 union smb_close io;
155 struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
156 struct smbcli_request *req;
158 break_info.fnum = fnum;
159 break_info.level = level;
160 break_info.count++;
162 io.close.level = RAW_CLOSE_CLOSE;
163 io.close.in.file.fnum = fnum;
164 io.close.in.write_time = 0;
165 req = smb_raw_close_send(tree, &io);
166 if (req == NULL) {
167 printf("failed to send close in oplock_handler_close\n");
168 return false;
171 req->async.fn = oplock_handler_close_recv;
172 req->async.private_data = NULL;
174 return true;
177 static bool open_connection_no_level2_oplocks(struct torture_context *tctx,
178 struct smbcli_state **c)
180 NTSTATUS status;
181 struct smbcli_options options;
182 struct smbcli_session_options session_options;
184 lp_smbcli_options(tctx->lp_ctx, &options);
185 lp_smbcli_session_options(tctx->lp_ctx, &session_options);
187 options.use_level2_oplocks = false;
189 status = smbcli_full_connection(tctx, c,
190 torture_setting_string(tctx, "host", NULL),
191 lp_smb_ports(tctx->lp_ctx),
192 torture_setting_string(tctx, "share", NULL),
193 NULL, lp_socket_options(tctx->lp_ctx), cmdline_credentials,
194 lp_resolve_context(tctx->lp_ctx),
195 tctx->ev, &options, &session_options,
196 lp_iconv_convenience(tctx->lp_ctx),
197 lp_gensec_settings(tctx, tctx->lp_ctx));
198 if (!NT_STATUS_IS_OK(status)) {
199 torture_comment(tctx, "Failed to open connection - %s\n",
200 nt_errstr(status));
201 return false;
204 return true;
207 static bool test_raw_oplock_exclusive1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
209 const char *fname = BASEDIR "\\test_exclusive1.dat";
210 NTSTATUS status;
211 bool ret = true;
212 union smb_open io;
213 union smb_unlink unl;
214 uint16_t fnum=0;
216 if (!torture_setup_dir(cli1, BASEDIR)) {
217 return false;
220 /* cleanup */
221 smbcli_unlink(cli1->tree, fname);
223 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
226 base ntcreatex parms
228 io.generic.level = RAW_OPEN_NTCREATEX;
229 io.ntcreatex.in.root_fid = 0;
230 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
231 io.ntcreatex.in.alloc_size = 0;
232 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
233 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
234 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
235 io.ntcreatex.in.create_options = 0;
236 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
237 io.ntcreatex.in.security_flags = 0;
238 io.ntcreatex.in.fname = fname;
240 torture_comment(tctx, "EXCLUSIVE1: open a file with an exclusive oplock (share mode: none)\n");
241 ZERO_STRUCT(break_info);
242 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
244 status = smb_raw_open(cli1->tree, tctx, &io);
245 CHECK_STATUS(tctx, status, NT_STATUS_OK);
246 fnum = io.ntcreatex.out.file.fnum;
247 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
249 torture_comment(tctx, "a 2nd open should not cause a break\n");
250 status = smb_raw_open(cli2->tree, tctx, &io);
251 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
252 CHECK_VAL(break_info.count, 0);
253 CHECK_VAL(break_info.failures, 0);
255 torture_comment(tctx, "unlink it - should also be no break\n");
256 unl.unlink.in.pattern = fname;
257 unl.unlink.in.attrib = 0;
258 status = smb_raw_unlink(cli2->tree, &unl);
259 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
260 CHECK_VAL(break_info.count, 0);
261 CHECK_VAL(break_info.failures, 0);
263 smbcli_close(cli1->tree, fnum);
265 done:
266 smb_raw_exit(cli1->session);
267 smb_raw_exit(cli2->session);
268 smbcli_deltree(cli1->tree, BASEDIR);
269 return ret;
272 static bool test_raw_oplock_exclusive2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
274 const char *fname = BASEDIR "\\test_exclusive2.dat";
275 NTSTATUS status;
276 bool ret = true;
277 union smb_open io;
278 union smb_unlink unl;
279 uint16_t fnum=0, fnum2=0;
281 if (!torture_setup_dir(cli1, BASEDIR)) {
282 return false;
285 /* cleanup */
286 smbcli_unlink(cli1->tree, fname);
288 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
291 base ntcreatex parms
293 io.generic.level = RAW_OPEN_NTCREATEX;
294 io.ntcreatex.in.root_fid = 0;
295 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
296 io.ntcreatex.in.alloc_size = 0;
297 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
298 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
299 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
300 io.ntcreatex.in.create_options = 0;
301 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
302 io.ntcreatex.in.security_flags = 0;
303 io.ntcreatex.in.fname = fname;
305 torture_comment(tctx, "EXCLUSIVE2: open a file with an exclusive oplock (share mode: all)\n");
306 ZERO_STRUCT(break_info);
307 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
308 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
309 NTCREATEX_SHARE_ACCESS_WRITE|
310 NTCREATEX_SHARE_ACCESS_DELETE;
312 status = smb_raw_open(cli1->tree, tctx, &io);
313 CHECK_STATUS(tctx, status, NT_STATUS_OK);
314 fnum = io.ntcreatex.out.file.fnum;
315 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
317 torture_comment(tctx, "a 2nd open should cause a break to level 2\n");
318 status = smb_raw_open(cli2->tree, tctx, &io);
319 CHECK_STATUS(tctx, status, NT_STATUS_OK);
320 fnum2 = io.ntcreatex.out.file.fnum;
321 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
322 CHECK_VAL(break_info.count, 1);
323 CHECK_VAL(break_info.fnum, fnum);
324 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
325 CHECK_VAL(break_info.failures, 0);
326 ZERO_STRUCT(break_info);
328 /* now we have 2 level II oplocks... */
329 torture_comment(tctx, "try to unlink it - should not cause a break, but a sharing violation\n");
330 unl.unlink.in.pattern = fname;
331 unl.unlink.in.attrib = 0;
332 status = smb_raw_unlink(cli2->tree, &unl);
333 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
334 CHECK_VAL(break_info.count, 0);
335 CHECK_VAL(break_info.failures, 0);
337 torture_comment(tctx, "close 1st handle\n");
338 smbcli_close(cli1->tree, fnum);
340 torture_comment(tctx, "try to unlink it - should not cause a break, but a sharing violation\n");
341 unl.unlink.in.pattern = fname;
342 unl.unlink.in.attrib = 0;
343 status = smb_raw_unlink(cli2->tree, &unl);
344 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
345 CHECK_VAL(break_info.count, 0);
346 CHECK_VAL(break_info.failures, 0);
348 torture_comment(tctx, "close 1st handle\n");
349 smbcli_close(cli2->tree, fnum2);
351 torture_comment(tctx, "unlink it\n");
352 unl.unlink.in.pattern = fname;
353 unl.unlink.in.attrib = 0;
354 status = smb_raw_unlink(cli2->tree, &unl);
355 CHECK_STATUS(tctx, status, NT_STATUS_OK);
356 CHECK_VAL(break_info.count, 0);
357 CHECK_VAL(break_info.failures, 0);
359 done:
360 smb_raw_exit(cli1->session);
361 smb_raw_exit(cli2->session);
362 smbcli_deltree(cli1->tree, BASEDIR);
363 return ret;
366 static bool test_raw_oplock_exclusive3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
368 const char *fname = BASEDIR "\\test_exclusive3.dat";
369 NTSTATUS status;
370 bool ret = true;
371 union smb_open io;
372 union smb_setfileinfo sfi;
373 uint16_t fnum=0;
375 if (!torture_setup_dir(cli1, BASEDIR)) {
376 return false;
379 /* cleanup */
380 smbcli_unlink(cli1->tree, fname);
382 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
385 base ntcreatex parms
387 io.generic.level = RAW_OPEN_NTCREATEX;
388 io.ntcreatex.in.root_fid = 0;
389 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
390 io.ntcreatex.in.alloc_size = 0;
391 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
392 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
393 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
394 io.ntcreatex.in.create_options = 0;
395 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
396 io.ntcreatex.in.security_flags = 0;
397 io.ntcreatex.in.fname = fname;
399 torture_comment(tctx, "EXCLUSIVE3: open a file with an exclusive oplock (share mode: none)\n");
401 ZERO_STRUCT(break_info);
402 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
404 status = smb_raw_open(cli1->tree, tctx, &io);
405 CHECK_STATUS(tctx, status, NT_STATUS_OK);
406 fnum = io.ntcreatex.out.file.fnum;
407 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
409 torture_comment(tctx, "setpathinfo EOF should trigger a break to none\n");
410 ZERO_STRUCT(sfi);
411 sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
412 sfi.generic.in.file.path = fname;
413 sfi.end_of_file_info.in.size = 100;
415 status = smb_raw_setpathinfo(cli2->tree, &sfi);
417 CHECK_STATUS(tctx, status, NT_STATUS_OK);
418 CHECK_VAL(break_info.count, 1);
419 CHECK_VAL(break_info.failures, 0);
420 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
422 smbcli_close(cli1->tree, fnum);
424 done:
425 smb_raw_exit(cli1->session);
426 smb_raw_exit(cli2->session);
427 smbcli_deltree(cli1->tree, BASEDIR);
428 return ret;
431 static bool test_raw_oplock_exclusive4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
433 const char *fname = BASEDIR "\\test_exclusive4.dat";
434 NTSTATUS status;
435 bool ret = true;
436 union smb_open io;
437 uint16_t fnum=0, fnum2=0;
439 if (!torture_setup_dir(cli1, BASEDIR)) {
440 return false;
443 /* cleanup */
444 smbcli_unlink(cli1->tree, fname);
446 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
449 base ntcreatex parms
451 io.generic.level = RAW_OPEN_NTCREATEX;
452 io.ntcreatex.in.root_fid = 0;
453 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
454 io.ntcreatex.in.alloc_size = 0;
455 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
456 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
457 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
458 io.ntcreatex.in.create_options = 0;
459 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
460 io.ntcreatex.in.security_flags = 0;
461 io.ntcreatex.in.fname = fname;
463 torture_comment(tctx, "EXCLUSIVE4: open with exclusive oplock\n");
464 ZERO_STRUCT(break_info);
465 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
467 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
468 status = smb_raw_open(cli1->tree, tctx, &io);
469 CHECK_STATUS(tctx, status, NT_STATUS_OK);
470 fnum = io.ntcreatex.out.file.fnum;
471 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
473 ZERO_STRUCT(break_info);
474 torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
476 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
477 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
478 status = smb_raw_open(cli2->tree, tctx, &io);
479 CHECK_STATUS(tctx, status, NT_STATUS_OK);
480 fnum2 = io.ntcreatex.out.file.fnum;
481 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
482 CHECK_VAL(break_info.count, 0);
483 CHECK_VAL(break_info.failures, 0);
485 smbcli_close(cli1->tree, fnum);
486 smbcli_close(cli2->tree, fnum2);
488 done:
489 smb_raw_exit(cli1->session);
490 smb_raw_exit(cli2->session);
491 smbcli_deltree(cli1->tree, BASEDIR);
492 return ret;
495 static bool test_raw_oplock_exclusive5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
497 const char *fname = BASEDIR "\\test_exclusive5.dat";
498 NTSTATUS status;
499 bool ret = true;
500 union smb_open io;
501 uint16_t fnum=0, fnum2=0;
503 if (!torture_setup_dir(cli1, BASEDIR)) {
504 return false;
507 /* cleanup */
508 smbcli_unlink(cli1->tree, fname);
510 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
511 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
514 base ntcreatex parms
516 io.generic.level = RAW_OPEN_NTCREATEX;
517 io.ntcreatex.in.root_fid = 0;
518 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
519 io.ntcreatex.in.alloc_size = 0;
520 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
521 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
522 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
523 io.ntcreatex.in.create_options = 0;
524 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
525 io.ntcreatex.in.security_flags = 0;
526 io.ntcreatex.in.fname = fname;
528 torture_comment(tctx, "EXCLUSIVE5: open with exclusive oplock\n");
529 ZERO_STRUCT(break_info);
530 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
533 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
534 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
535 NTCREATEX_SHARE_ACCESS_WRITE|
536 NTCREATEX_SHARE_ACCESS_DELETE;
537 status = smb_raw_open(cli1->tree, tctx, &io);
538 CHECK_STATUS(tctx, status, NT_STATUS_OK);
539 fnum = io.ntcreatex.out.file.fnum;
540 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
542 ZERO_STRUCT(break_info);
544 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
546 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
547 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
548 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
549 status = smb_raw_open(cli2->tree, tctx, &io);
550 CHECK_STATUS(tctx, status, NT_STATUS_OK);
551 fnum2 = io.ntcreatex.out.file.fnum;
552 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
553 CHECK_VAL(break_info.count, 1);
554 CHECK_VAL(break_info.failures, 0);
556 smbcli_close(cli1->tree, fnum);
557 smbcli_close(cli2->tree, fnum2);
559 done:
560 smb_raw_exit(cli1->session);
561 smb_raw_exit(cli2->session);
562 smbcli_deltree(cli1->tree, BASEDIR);
563 return ret;
566 static bool test_raw_oplock_exclusive6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
568 const char *fname1 = BASEDIR "\\test_exclusive6_1.dat";
569 const char *fname2 = BASEDIR "\\test_exclusive6_2.dat";
570 NTSTATUS status;
571 bool ret = true;
572 union smb_open io;
573 union smb_rename rn;
574 uint16_t fnum=0;
576 if (!torture_setup_dir(cli1, BASEDIR)) {
577 return false;
580 /* cleanup */
581 smbcli_unlink(cli1->tree, fname1);
582 smbcli_unlink(cli1->tree, fname2);
584 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
587 base ntcreatex parms
589 io.generic.level = RAW_OPEN_NTCREATEX;
590 io.ntcreatex.in.root_fid = 0;
591 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
592 io.ntcreatex.in.alloc_size = 0;
593 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
594 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
595 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
596 io.ntcreatex.in.create_options = 0;
597 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
598 io.ntcreatex.in.security_flags = 0;
599 io.ntcreatex.in.fname = fname1;
601 torture_comment(tctx, "EXCLUSIVE6: open a file with an exclusive "
602 "oplock (share mode: none)\n");
603 ZERO_STRUCT(break_info);
604 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
606 status = smb_raw_open(cli1->tree, tctx, &io);
607 CHECK_STATUS(tctx, status, NT_STATUS_OK);
608 fnum = io.ntcreatex.out.file.fnum;
609 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
611 torture_comment(tctx, "rename should not generate a break but get a "
612 "sharing violation\n");
613 ZERO_STRUCT(rn);
614 rn.generic.level = RAW_RENAME_RENAME;
615 rn.rename.in.pattern1 = fname1;
616 rn.rename.in.pattern2 = fname2;
617 rn.rename.in.attrib = 0;
619 torture_comment(tctx, "trying rename while first file open\n");
620 status = smb_raw_rename(cli2->tree, &rn);
622 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
623 CHECK_VAL(break_info.count, 0);
624 CHECK_VAL(break_info.failures, 0);
626 smbcli_close(cli1->tree, fnum);
628 done:
629 smb_raw_exit(cli1->session);
630 smb_raw_exit(cli2->session);
631 smbcli_deltree(cli1->tree, BASEDIR);
632 return ret;
635 static bool test_raw_oplock_batch1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
637 const char *fname = BASEDIR "\\test_batch1.dat";
638 NTSTATUS status;
639 bool ret = true;
640 union smb_open io;
641 union smb_unlink unl;
642 uint16_t fnum=0;
643 char c = 0;
645 if (!torture_setup_dir(cli1, BASEDIR)) {
646 return false;
649 /* cleanup */
650 smbcli_unlink(cli1->tree, fname);
652 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
655 base ntcreatex parms
657 io.generic.level = RAW_OPEN_NTCREATEX;
658 io.ntcreatex.in.root_fid = 0;
659 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
660 io.ntcreatex.in.alloc_size = 0;
661 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
662 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
663 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
664 io.ntcreatex.in.create_options = 0;
665 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
666 io.ntcreatex.in.security_flags = 0;
667 io.ntcreatex.in.fname = fname;
670 with a batch oplock we get a break
672 torture_comment(tctx, "BATCH1: open with batch oplock\n");
673 ZERO_STRUCT(break_info);
674 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
675 NTCREATEX_FLAGS_REQUEST_OPLOCK |
676 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
677 status = smb_raw_open(cli1->tree, tctx, &io);
678 CHECK_STATUS(tctx, status, NT_STATUS_OK);
679 fnum = io.ntcreatex.out.file.fnum;
680 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
682 torture_comment(tctx, "unlink should generate a break\n");
683 unl.unlink.in.pattern = fname;
684 unl.unlink.in.attrib = 0;
685 status = smb_raw_unlink(cli2->tree, &unl);
686 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
688 CHECK_VAL(break_info.count, 1);
689 CHECK_VAL(break_info.fnum, fnum);
690 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
691 CHECK_VAL(break_info.failures, 0);
693 torture_comment(tctx, "2nd unlink should not generate a break\n");
694 ZERO_STRUCT(break_info);
695 status = smb_raw_unlink(cli2->tree, &unl);
696 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
698 CHECK_VAL(break_info.count, 0);
700 torture_comment(tctx, "writing should generate a self break to none\n");
701 smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
702 msleep(100);
703 smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
705 CHECK_VAL(break_info.count, 1);
706 CHECK_VAL(break_info.fnum, fnum);
707 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
708 CHECK_VAL(break_info.failures, 0);
710 smbcli_close(cli1->tree, fnum);
712 done:
713 smb_raw_exit(cli1->session);
714 smb_raw_exit(cli2->session);
715 smbcli_deltree(cli1->tree, BASEDIR);
716 return ret;
719 static bool test_raw_oplock_batch2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
721 const char *fname = BASEDIR "\\test_batch2.dat";
722 NTSTATUS status;
723 bool ret = true;
724 union smb_open io;
725 union smb_unlink unl;
726 uint16_t fnum=0;
727 char c = 0;
729 if (!torture_setup_dir(cli1, BASEDIR)) {
730 return false;
733 /* cleanup */
734 smbcli_unlink(cli1->tree, fname);
736 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
739 base ntcreatex parms
741 io.generic.level = RAW_OPEN_NTCREATEX;
742 io.ntcreatex.in.root_fid = 0;
743 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
744 io.ntcreatex.in.alloc_size = 0;
745 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
746 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
747 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
748 io.ntcreatex.in.create_options = 0;
749 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
750 io.ntcreatex.in.security_flags = 0;
751 io.ntcreatex.in.fname = fname;
753 torture_comment(tctx, "BATCH2: open with batch oplock\n");
754 ZERO_STRUCT(break_info);
755 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
756 NTCREATEX_FLAGS_REQUEST_OPLOCK |
757 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
758 status = smb_raw_open(cli1->tree, tctx, &io);
759 CHECK_STATUS(tctx, status, NT_STATUS_OK);
760 fnum = io.ntcreatex.out.file.fnum;
761 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
763 torture_comment(tctx, "unlink should generate a break, which we ack as break to none\n");
764 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_none, cli1->tree);
765 unl.unlink.in.pattern = fname;
766 unl.unlink.in.attrib = 0;
767 status = smb_raw_unlink(cli2->tree, &unl);
768 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
770 CHECK_VAL(break_info.count, 1);
771 CHECK_VAL(break_info.fnum, fnum);
772 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
773 CHECK_VAL(break_info.failures, 0);
775 torture_comment(tctx, "2nd unlink should not generate a break\n");
776 ZERO_STRUCT(break_info);
777 status = smb_raw_unlink(cli2->tree, &unl);
778 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
780 CHECK_VAL(break_info.count, 0);
782 torture_comment(tctx, "writing should not generate a break\n");
783 smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
784 msleep(100);
785 smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
787 CHECK_VAL(break_info.count, 0);
789 smbcli_close(cli1->tree, fnum);
791 done:
792 smb_raw_exit(cli1->session);
793 smb_raw_exit(cli2->session);
794 smbcli_deltree(cli1->tree, BASEDIR);
795 return ret;
798 static bool test_raw_oplock_batch3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
800 const char *fname = BASEDIR "\\test_batch3.dat";
801 NTSTATUS status;
802 bool ret = true;
803 union smb_open io;
804 union smb_unlink unl;
805 uint16_t fnum=0;
807 if (!torture_setup_dir(cli1, BASEDIR)) {
808 return false;
811 /* cleanup */
812 smbcli_unlink(cli1->tree, fname);
814 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
817 base ntcreatex parms
819 io.generic.level = RAW_OPEN_NTCREATEX;
820 io.ntcreatex.in.root_fid = 0;
821 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
822 io.ntcreatex.in.alloc_size = 0;
823 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
824 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
825 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
826 io.ntcreatex.in.create_options = 0;
827 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
828 io.ntcreatex.in.security_flags = 0;
829 io.ntcreatex.in.fname = fname;
831 torture_comment(tctx, "BATCH3: if we close on break then the unlink can succeed\n");
832 ZERO_STRUCT(break_info);
833 smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
834 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
835 NTCREATEX_FLAGS_REQUEST_OPLOCK |
836 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
837 status = smb_raw_open(cli1->tree, tctx, &io);
838 CHECK_STATUS(tctx, status, NT_STATUS_OK);
839 fnum = io.ntcreatex.out.file.fnum;
840 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
842 unl.unlink.in.pattern = fname;
843 unl.unlink.in.attrib = 0;
844 ZERO_STRUCT(break_info);
845 status = smb_raw_unlink(cli2->tree, &unl);
846 CHECK_STATUS(tctx, status, NT_STATUS_OK);
848 CHECK_VAL(break_info.count, 1);
849 CHECK_VAL(break_info.fnum, fnum);
850 CHECK_VAL(break_info.level, 1);
851 CHECK_VAL(break_info.failures, 0);
853 smbcli_close(cli1->tree, fnum);
855 done:
856 smb_raw_exit(cli1->session);
857 smb_raw_exit(cli2->session);
858 smbcli_deltree(cli1->tree, BASEDIR);
859 return ret;
862 static bool test_raw_oplock_batch4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
864 const char *fname = BASEDIR "\\test_batch4.dat";
865 NTSTATUS status;
866 bool ret = true;
867 union smb_open io;
868 union smb_read rd;
869 uint16_t fnum=0;
871 if (!torture_setup_dir(cli1, BASEDIR)) {
872 return false;
875 /* cleanup */
876 smbcli_unlink(cli1->tree, fname);
878 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
881 base ntcreatex parms
883 io.generic.level = RAW_OPEN_NTCREATEX;
884 io.ntcreatex.in.root_fid = 0;
885 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
886 io.ntcreatex.in.alloc_size = 0;
887 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
888 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
889 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
890 io.ntcreatex.in.create_options = 0;
891 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
892 io.ntcreatex.in.security_flags = 0;
893 io.ntcreatex.in.fname = fname;
895 torture_comment(tctx, "BATCH4: a self read should not cause a break\n");
896 ZERO_STRUCT(break_info);
897 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
899 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
900 NTCREATEX_FLAGS_REQUEST_OPLOCK |
901 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
902 status = smb_raw_open(cli1->tree, tctx, &io);
903 CHECK_STATUS(tctx, status, NT_STATUS_OK);
904 fnum = io.ntcreatex.out.file.fnum;
905 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
907 rd.read.level = RAW_READ_READ;
908 rd.read.in.file.fnum = fnum;
909 rd.read.in.count = 1;
910 rd.read.in.offset = 0;
911 rd.read.in.remaining = 0;
912 status = smb_raw_read(cli1->tree, &rd);
913 CHECK_STATUS(tctx, status, NT_STATUS_OK);
914 CHECK_VAL(break_info.count, 0);
915 CHECK_VAL(break_info.failures, 0);
917 smbcli_close(cli1->tree, fnum);
919 done:
920 smb_raw_exit(cli1->session);
921 smb_raw_exit(cli2->session);
922 smbcli_deltree(cli1->tree, BASEDIR);
923 return ret;
926 static bool test_raw_oplock_batch5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
928 const char *fname = BASEDIR "\\test_batch5.dat";
929 NTSTATUS status;
930 bool ret = true;
931 union smb_open io;
932 uint16_t fnum=0;
934 if (!torture_setup_dir(cli1, BASEDIR)) {
935 return false;
938 /* cleanup */
939 smbcli_unlink(cli1->tree, fname);
941 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
944 base ntcreatex parms
946 io.generic.level = RAW_OPEN_NTCREATEX;
947 io.ntcreatex.in.root_fid = 0;
948 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
949 io.ntcreatex.in.alloc_size = 0;
950 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
951 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
952 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
953 io.ntcreatex.in.create_options = 0;
954 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
955 io.ntcreatex.in.security_flags = 0;
956 io.ntcreatex.in.fname = fname;
958 torture_comment(tctx, "BATCH5: a 2nd open should give a break\n");
959 ZERO_STRUCT(break_info);
960 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
962 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
963 NTCREATEX_FLAGS_REQUEST_OPLOCK |
964 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
965 status = smb_raw_open(cli1->tree, tctx, &io);
966 CHECK_STATUS(tctx, status, NT_STATUS_OK);
967 fnum = io.ntcreatex.out.file.fnum;
968 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
970 ZERO_STRUCT(break_info);
972 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
973 status = smb_raw_open(cli2->tree, tctx, &io);
974 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
976 CHECK_VAL(break_info.count, 1);
977 CHECK_VAL(break_info.fnum, fnum);
978 CHECK_VAL(break_info.level, 1);
979 CHECK_VAL(break_info.failures, 0);
981 smbcli_close(cli1->tree, fnum);
983 done:
984 smb_raw_exit(cli1->session);
985 smb_raw_exit(cli2->session);
986 smbcli_deltree(cli1->tree, BASEDIR);
987 return ret;
990 static bool test_raw_oplock_batch6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
992 const char *fname = BASEDIR "\\test_batch6.dat";
993 NTSTATUS status;
994 bool ret = true;
995 union smb_open io;
996 uint16_t fnum=0, fnum2=0;
997 char c = 0;
999 if (!torture_setup_dir(cli1, BASEDIR)) {
1000 return false;
1003 /* cleanup */
1004 smbcli_unlink(cli1->tree, fname);
1006 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1009 base ntcreatex parms
1011 io.generic.level = RAW_OPEN_NTCREATEX;
1012 io.ntcreatex.in.root_fid = 0;
1013 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1014 io.ntcreatex.in.alloc_size = 0;
1015 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1016 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1017 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1018 io.ntcreatex.in.create_options = 0;
1019 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1020 io.ntcreatex.in.security_flags = 0;
1021 io.ntcreatex.in.fname = fname;
1023 torture_comment(tctx, "BATCH6: a 2nd open should give a break to level II if the first open allowed shared read\n");
1024 ZERO_STRUCT(break_info);
1025 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1026 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1028 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
1029 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
1030 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1031 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1032 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1033 status = smb_raw_open(cli1->tree, tctx, &io);
1034 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1035 fnum = io.ntcreatex.out.file.fnum;
1036 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1038 ZERO_STRUCT(break_info);
1040 status = smb_raw_open(cli2->tree, tctx, &io);
1041 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1042 fnum2 = io.ntcreatex.out.file.fnum;
1043 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1045 CHECK_VAL(break_info.count, 1);
1046 CHECK_VAL(break_info.fnum, fnum);
1047 CHECK_VAL(break_info.level, 1);
1048 CHECK_VAL(break_info.failures, 0);
1049 ZERO_STRUCT(break_info);
1051 torture_comment(tctx, "write should trigger a break to none on both\n");
1052 smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
1053 msleep(100);
1054 smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
1056 CHECK_VAL(break_info.count, 2);
1057 CHECK_VAL(break_info.level, 0);
1058 CHECK_VAL(break_info.failures, 0);
1060 smbcli_close(cli1->tree, fnum);
1061 smbcli_close(cli2->tree, fnum2);
1064 done:
1065 smb_raw_exit(cli1->session);
1066 smb_raw_exit(cli2->session);
1067 smbcli_deltree(cli1->tree, BASEDIR);
1068 return ret;
1071 static bool test_raw_oplock_batch7(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1073 const char *fname = BASEDIR "\\test_batch7.dat";
1074 NTSTATUS status;
1075 bool ret = true;
1076 union smb_open io;
1077 uint16_t fnum=0, fnum2=0;
1079 if (!torture_setup_dir(cli1, BASEDIR)) {
1080 return false;
1083 /* cleanup */
1084 smbcli_unlink(cli1->tree, fname);
1086 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1089 base ntcreatex parms
1091 io.generic.level = RAW_OPEN_NTCREATEX;
1092 io.ntcreatex.in.root_fid = 0;
1093 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1094 io.ntcreatex.in.alloc_size = 0;
1095 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1096 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1097 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1098 io.ntcreatex.in.create_options = 0;
1099 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1100 io.ntcreatex.in.security_flags = 0;
1101 io.ntcreatex.in.fname = fname;
1103 torture_comment(tctx, "BATCH7: a 2nd open should get an oplock when we close instead of ack\n");
1104 ZERO_STRUCT(break_info);
1105 smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
1107 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1108 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1109 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1110 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1111 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1112 status = smb_raw_open(cli1->tree, tctx, &io);
1113 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1114 fnum2 = io.ntcreatex.out.file.fnum;
1115 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1117 ZERO_STRUCT(break_info);
1119 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1120 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1121 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1122 status = smb_raw_open(cli2->tree, tctx, &io);
1123 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1124 fnum = io.ntcreatex.out.file.fnum;
1125 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1127 CHECK_VAL(break_info.count, 1);
1128 CHECK_VAL(break_info.fnum, fnum2);
1129 CHECK_VAL(break_info.level, 1);
1130 CHECK_VAL(break_info.failures, 0);
1132 smbcli_close(cli2->tree, fnum);
1134 done:
1135 smb_raw_exit(cli1->session);
1136 smb_raw_exit(cli2->session);
1137 smbcli_deltree(cli1->tree, BASEDIR);
1138 return ret;
1141 static bool test_raw_oplock_batch8(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1143 const char *fname = BASEDIR "\\test_batch8.dat";
1144 NTSTATUS status;
1145 bool ret = true;
1146 union smb_open io;
1147 uint16_t fnum=0, fnum2=0;
1149 if (!torture_setup_dir(cli1, BASEDIR)) {
1150 return false;
1153 /* cleanup */
1154 smbcli_unlink(cli1->tree, fname);
1156 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1159 base ntcreatex parms
1161 io.generic.level = RAW_OPEN_NTCREATEX;
1162 io.ntcreatex.in.root_fid = 0;
1163 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1164 io.ntcreatex.in.alloc_size = 0;
1165 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1166 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1167 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1168 io.ntcreatex.in.create_options = 0;
1169 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1170 io.ntcreatex.in.security_flags = 0;
1171 io.ntcreatex.in.fname = fname;
1173 torture_comment(tctx, "BATCH8: open with batch oplock\n");
1174 ZERO_STRUCT(break_info);
1175 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1177 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1178 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1179 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1180 status = smb_raw_open(cli1->tree, tctx, &io);
1181 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1182 fnum = io.ntcreatex.out.file.fnum;
1183 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1185 ZERO_STRUCT(break_info);
1186 torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
1188 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1189 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1190 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1191 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1192 status = smb_raw_open(cli2->tree, tctx, &io);
1193 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1194 fnum2 = io.ntcreatex.out.file.fnum;
1195 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
1196 CHECK_VAL(break_info.count, 0);
1197 CHECK_VAL(break_info.failures, 0);
1199 smbcli_close(cli1->tree, fnum);
1200 smbcli_close(cli2->tree, fnum2);
1202 done:
1203 smb_raw_exit(cli1->session);
1204 smb_raw_exit(cli2->session);
1205 smbcli_deltree(cli1->tree, BASEDIR);
1206 return ret;
1209 static bool test_raw_oplock_batch9(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1211 const char *fname = BASEDIR "\\test_batch9.dat";
1212 NTSTATUS status;
1213 bool ret = true;
1214 union smb_open io;
1215 uint16_t fnum=0, fnum2=0;
1216 char c = 0;
1218 if (!torture_setup_dir(cli1, BASEDIR)) {
1219 return false;
1222 /* cleanup */
1223 smbcli_unlink(cli1->tree, fname);
1225 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1228 base ntcreatex parms
1230 io.generic.level = RAW_OPEN_NTCREATEX;
1231 io.ntcreatex.in.root_fid = 0;
1232 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1233 io.ntcreatex.in.alloc_size = 0;
1234 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1235 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1236 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1237 io.ntcreatex.in.create_options = 0;
1238 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1239 io.ntcreatex.in.security_flags = 0;
1240 io.ntcreatex.in.fname = fname;
1242 torture_comment(tctx, "BATCH9: open with attributes only can create file\n");
1244 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1245 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1246 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1247 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1248 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1249 status = smb_raw_open(cli1->tree, tctx, &io);
1250 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1251 fnum = io.ntcreatex.out.file.fnum;
1252 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1254 torture_comment(tctx, "Subsequent normal open should break oplock on attribute only open to level II\n");
1256 ZERO_STRUCT(break_info);
1257 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1259 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1260 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1261 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1262 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1263 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1264 status = smb_raw_open(cli2->tree, tctx, &io);
1265 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1266 fnum2 = io.ntcreatex.out.file.fnum;
1267 CHECK_VAL(break_info.count, 1);
1268 CHECK_VAL(break_info.fnum, fnum);
1269 CHECK_VAL(break_info.failures, 0);
1270 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1271 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1272 smbcli_close(cli2->tree, fnum2);
1274 torture_comment(tctx, "third oplocked open should grant level2 without break\n");
1275 ZERO_STRUCT(break_info);
1276 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1277 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1278 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1279 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1280 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1281 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1282 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1283 status = smb_raw_open(cli2->tree, tctx, &io);
1284 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1285 fnum2 = io.ntcreatex.out.file.fnum;
1286 CHECK_VAL(break_info.count, 0);
1287 CHECK_VAL(break_info.failures, 0);
1288 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1290 ZERO_STRUCT(break_info);
1292 torture_comment(tctx, "write should trigger a break to none on both\n");
1293 smbcli_write(cli2->tree, fnum2, 0, &c, 0, 1);
1295 /* Now the oplock break request comes in. But right now we can't
1296 * answer it. Do another write */
1298 msleep(100);
1299 smbcli_write(cli2->tree, fnum2, 0, &c, 1, 1);
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_batch10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1317 const char *fname = BASEDIR "\\test_batch10.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 = 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, "BATCH10: Open with oplock after a non-oplock open should grant level2\n");
1348 ZERO_STRUCT(break_info);
1349 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1350 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1351 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1352 NTCREATEX_SHARE_ACCESS_WRITE|
1353 NTCREATEX_SHARE_ACCESS_DELETE;
1354 status = smb_raw_open(cli1->tree, tctx, &io);
1355 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1356 fnum = io.ntcreatex.out.file.fnum;
1357 CHECK_VAL(break_info.count, 0);
1358 CHECK_VAL(break_info.failures, 0);
1359 CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
1361 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1363 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1364 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1365 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1366 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1367 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1368 NTCREATEX_SHARE_ACCESS_WRITE|
1369 NTCREATEX_SHARE_ACCESS_DELETE;
1370 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1371 status = smb_raw_open(cli2->tree, tctx, &io);
1372 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1373 fnum2 = io.ntcreatex.out.file.fnum;
1374 CHECK_VAL(break_info.count, 0);
1375 CHECK_VAL(break_info.failures, 0);
1376 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1378 torture_comment(tctx, "write should trigger a break to none\n");
1380 union smb_write wr;
1381 wr.write.level = RAW_WRITE_WRITE;
1382 wr.write.in.file.fnum = fnum;
1383 wr.write.in.count = 1;
1384 wr.write.in.offset = 0;
1385 wr.write.in.remaining = 0;
1386 wr.write.in.data = (const uint8_t *)"x";
1387 status = smb_raw_write(cli1->tree, &wr);
1388 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1391 /* Now the oplock break request comes in. But right now we can't
1392 * answer it. Do another write */
1394 msleep(100);
1397 union smb_write wr;
1398 wr.write.level = RAW_WRITE_WRITE;
1399 wr.write.in.file.fnum = fnum;
1400 wr.write.in.count = 1;
1401 wr.write.in.offset = 0;
1402 wr.write.in.remaining = 0;
1403 wr.write.in.data = (const uint8_t *)"x";
1404 status = smb_raw_write(cli1->tree, &wr);
1405 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1408 CHECK_VAL(break_info.count, 1);
1409 CHECK_VAL(break_info.fnum, fnum2);
1410 CHECK_VAL(break_info.level, 0);
1411 CHECK_VAL(break_info.failures, 0);
1413 smbcli_close(cli1->tree, fnum);
1414 smbcli_close(cli2->tree, fnum2);
1416 done:
1417 smb_raw_exit(cli1->session);
1418 smb_raw_exit(cli2->session);
1419 smbcli_deltree(cli1->tree, BASEDIR);
1420 return ret;
1423 static bool test_raw_oplock_batch11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1425 const char *fname = BASEDIR "\\test_batch11.dat";
1426 NTSTATUS status;
1427 bool ret = true;
1428 union smb_open io;
1429 union smb_setfileinfo sfi;
1430 uint16_t fnum=0;
1432 if (!torture_setup_dir(cli1, BASEDIR)) {
1433 return false;
1436 /* cleanup */
1437 smbcli_unlink(cli1->tree, fname);
1439 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1442 base ntcreatex parms
1444 io.generic.level = RAW_OPEN_NTCREATEX;
1445 io.ntcreatex.in.root_fid = 0;
1446 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1447 io.ntcreatex.in.alloc_size = 0;
1448 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1449 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1450 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1451 io.ntcreatex.in.create_options = 0;
1452 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1453 io.ntcreatex.in.security_flags = 0;
1454 io.ntcreatex.in.fname = fname;
1456 /* Test if a set-eof on pathname breaks an exclusive oplock. */
1457 torture_comment(tctx, "BATCH11: Test if setpathinfo set EOF breaks oplocks.\n");
1459 ZERO_STRUCT(break_info);
1460 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1462 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1463 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1464 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1465 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1466 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1467 NTCREATEX_SHARE_ACCESS_WRITE|
1468 NTCREATEX_SHARE_ACCESS_DELETE;
1469 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1470 status = smb_raw_open(cli1->tree, tctx, &io);
1471 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1472 fnum = io.ntcreatex.out.file.fnum;
1473 CHECK_VAL(break_info.count, 0);
1474 CHECK_VAL(break_info.failures, 0);
1475 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1477 ZERO_STRUCT(sfi);
1478 sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1479 sfi.generic.in.file.path = fname;
1480 sfi.end_of_file_info.in.size = 100;
1482 status = smb_raw_setpathinfo(cli2->tree, &sfi);
1484 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1485 CHECK_VAL(break_info.count, 1);
1486 CHECK_VAL(break_info.failures, 0);
1487 CHECK_VAL(break_info.level, 0);
1489 smbcli_close(cli1->tree, fnum);
1491 done:
1492 smb_raw_exit(cli1->session);
1493 smb_raw_exit(cli2->session);
1494 smbcli_deltree(cli1->tree, BASEDIR);
1495 return ret;
1498 static bool test_raw_oplock_batch12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1500 const char *fname = BASEDIR "\\test_batch12.dat";
1501 NTSTATUS status;
1502 bool ret = true;
1503 union smb_open io;
1504 union smb_setfileinfo sfi;
1505 uint16_t fnum=0;
1507 if (!torture_setup_dir(cli1, BASEDIR)) {
1508 return false;
1511 /* cleanup */
1512 smbcli_unlink(cli1->tree, fname);
1514 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1517 base ntcreatex parms
1519 io.generic.level = RAW_OPEN_NTCREATEX;
1520 io.ntcreatex.in.root_fid = 0;
1521 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1522 io.ntcreatex.in.alloc_size = 0;
1523 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1524 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1525 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1526 io.ntcreatex.in.create_options = 0;
1527 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1528 io.ntcreatex.in.security_flags = 0;
1529 io.ntcreatex.in.fname = fname;
1531 /* Test if a set-allocation size on pathname breaks an exclusive oplock. */
1532 torture_comment(tctx, "BATCH12: Test if setpathinfo allocation size breaks oplocks.\n");
1534 ZERO_STRUCT(break_info);
1535 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1537 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1538 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1539 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1540 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1541 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1542 NTCREATEX_SHARE_ACCESS_WRITE|
1543 NTCREATEX_SHARE_ACCESS_DELETE;
1544 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1545 status = smb_raw_open(cli1->tree, tctx, &io);
1546 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1547 fnum = io.ntcreatex.out.file.fnum;
1548 CHECK_VAL(break_info.count, 0);
1549 CHECK_VAL(break_info.failures, 0);
1550 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1552 ZERO_STRUCT(sfi);
1553 sfi.generic.level = SMB_SFILEINFO_ALLOCATION_INFORMATION;
1554 sfi.generic.in.file.path = fname;
1555 sfi.allocation_info.in.alloc_size = 65536 * 8;
1557 status = smb_raw_setpathinfo(cli2->tree, &sfi);
1559 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1560 CHECK_VAL(break_info.count, 1);
1561 CHECK_VAL(break_info.failures, 0);
1562 CHECK_VAL(break_info.level, 0);
1564 smbcli_close(cli1->tree, fnum);
1566 done:
1567 smb_raw_exit(cli1->session);
1568 smb_raw_exit(cli2->session);
1569 smbcli_deltree(cli1->tree, BASEDIR);
1570 return ret;
1573 static bool test_raw_oplock_batch13(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1575 const char *fname = BASEDIR "\\test_batch13.dat";
1576 NTSTATUS status;
1577 bool ret = true;
1578 union smb_open io;
1579 uint16_t fnum=0, fnum2=0;
1581 if (!torture_setup_dir(cli1, BASEDIR)) {
1582 return false;
1585 /* cleanup */
1586 smbcli_unlink(cli1->tree, fname);
1588 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1589 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
1592 base ntcreatex parms
1594 io.generic.level = RAW_OPEN_NTCREATEX;
1595 io.ntcreatex.in.root_fid = 0;
1596 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1597 io.ntcreatex.in.alloc_size = 0;
1598 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1599 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1600 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1601 io.ntcreatex.in.create_options = 0;
1602 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1603 io.ntcreatex.in.security_flags = 0;
1604 io.ntcreatex.in.fname = fname;
1606 torture_comment(tctx, "BATCH13: open with batch oplock\n");
1607 ZERO_STRUCT(break_info);
1608 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1611 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1612 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1613 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1614 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1615 NTCREATEX_SHARE_ACCESS_WRITE|
1616 NTCREATEX_SHARE_ACCESS_DELETE;
1617 status = smb_raw_open(cli1->tree, tctx, &io);
1618 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1619 fnum = io.ntcreatex.out.file.fnum;
1620 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1622 ZERO_STRUCT(break_info);
1624 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE dispostion causes oplock break\n");
1626 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1627 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1628 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1629 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1630 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1631 NTCREATEX_SHARE_ACCESS_WRITE|
1632 NTCREATEX_SHARE_ACCESS_DELETE;
1633 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
1634 status = smb_raw_open(cli2->tree, tctx, &io);
1635 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1636 fnum2 = io.ntcreatex.out.file.fnum;
1637 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1638 CHECK_VAL(break_info.count, 1);
1639 CHECK_VAL(break_info.failures, 0);
1641 smbcli_close(cli1->tree, fnum);
1642 smbcli_close(cli2->tree, fnum2);
1644 done:
1645 smb_raw_exit(cli1->session);
1646 smb_raw_exit(cli2->session);
1647 smbcli_deltree(cli1->tree, BASEDIR);
1648 return ret;
1651 static bool test_raw_oplock_batch14(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1653 const char *fname = BASEDIR "\\test_batch14.dat";
1654 NTSTATUS status;
1655 bool ret = true;
1656 union smb_open io;
1657 uint16_t fnum=0, fnum2=0;
1659 if (!torture_setup_dir(cli1, BASEDIR)) {
1660 return false;
1663 /* cleanup */
1664 smbcli_unlink(cli1->tree, fname);
1666 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1669 base ntcreatex parms
1671 io.generic.level = RAW_OPEN_NTCREATEX;
1672 io.ntcreatex.in.root_fid = 0;
1673 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1674 io.ntcreatex.in.alloc_size = 0;
1675 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1676 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1677 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1678 io.ntcreatex.in.create_options = 0;
1679 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1680 io.ntcreatex.in.security_flags = 0;
1681 io.ntcreatex.in.fname = fname;
1683 torture_comment(tctx, "BATCH14: open with batch oplock\n");
1684 ZERO_STRUCT(break_info);
1685 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1687 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1688 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1689 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1690 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1691 NTCREATEX_SHARE_ACCESS_WRITE|
1692 NTCREATEX_SHARE_ACCESS_DELETE;
1693 status = smb_raw_open(cli1->tree, tctx, &io);
1694 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1695 fnum = io.ntcreatex.out.file.fnum;
1696 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1698 ZERO_STRUCT(break_info);
1700 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_SUPERSEDE dispostion causes oplock break\n");
1702 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1703 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1704 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1705 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1706 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1707 NTCREATEX_SHARE_ACCESS_WRITE|
1708 NTCREATEX_SHARE_ACCESS_DELETE;
1709 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
1710 status = smb_raw_open(cli2->tree, tctx, &io);
1711 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1712 fnum2 = io.ntcreatex.out.file.fnum;
1713 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1714 CHECK_VAL(break_info.count, 1);
1715 CHECK_VAL(break_info.failures, 0);
1717 smbcli_close(cli1->tree, fnum);
1718 smbcli_close(cli2->tree, fnum2);
1719 done:
1720 smb_raw_exit(cli1->session);
1721 smb_raw_exit(cli2->session);
1722 smbcli_deltree(cli1->tree, BASEDIR);
1723 return ret;
1726 static bool test_raw_oplock_batch15(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1728 const char *fname = BASEDIR "\\test_batch15.dat";
1729 NTSTATUS status;
1730 bool ret = true;
1731 union smb_open io;
1732 union smb_fileinfo qfi;
1733 uint16_t fnum=0;
1735 if (!torture_setup_dir(cli1, BASEDIR)) {
1736 return false;
1739 /* cleanup */
1740 smbcli_unlink(cli1->tree, fname);
1742 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1745 base ntcreatex parms
1747 io.generic.level = RAW_OPEN_NTCREATEX;
1748 io.ntcreatex.in.root_fid = 0;
1749 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1750 io.ntcreatex.in.alloc_size = 0;
1751 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1752 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1753 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1754 io.ntcreatex.in.create_options = 0;
1755 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1756 io.ntcreatex.in.security_flags = 0;
1757 io.ntcreatex.in.fname = fname;
1759 /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
1760 torture_comment(tctx, "BATCH15: Test if qpathinfo all info breaks a batch oplock (should not).\n");
1762 ZERO_STRUCT(break_info);
1763 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1765 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1766 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1767 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1768 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1769 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1770 NTCREATEX_SHARE_ACCESS_WRITE|
1771 NTCREATEX_SHARE_ACCESS_DELETE;
1772 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1773 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1774 status = smb_raw_open(cli1->tree, tctx, &io);
1775 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1776 fnum = io.ntcreatex.out.file.fnum;
1777 CHECK_VAL(break_info.count, 0);
1778 CHECK_VAL(break_info.failures, 0);
1779 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1781 ZERO_STRUCT(qfi);
1782 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1783 qfi.generic.in.file.path = fname;
1785 status = smb_raw_pathinfo(cli2->tree, tctx, &qfi);
1787 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1788 CHECK_VAL(break_info.count, 0);
1790 smbcli_close(cli1->tree, fnum);
1792 done:
1793 smb_raw_exit(cli1->session);
1794 smb_raw_exit(cli2->session);
1795 smbcli_deltree(cli1->tree, BASEDIR);
1796 return ret;
1799 static bool test_raw_oplock_batch16(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1801 const char *fname = BASEDIR "\\test_batch16.dat";
1802 NTSTATUS status;
1803 bool ret = true;
1804 union smb_open io;
1805 uint16_t fnum=0, fnum2=0;
1807 if (!torture_setup_dir(cli1, BASEDIR)) {
1808 return false;
1811 /* cleanup */
1812 smbcli_unlink(cli1->tree, fname);
1814 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1815 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
1818 base ntcreatex parms
1820 io.generic.level = RAW_OPEN_NTCREATEX;
1821 io.ntcreatex.in.root_fid = 0;
1822 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1823 io.ntcreatex.in.alloc_size = 0;
1824 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1825 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1826 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1827 io.ntcreatex.in.create_options = 0;
1828 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1829 io.ntcreatex.in.security_flags = 0;
1830 io.ntcreatex.in.fname = fname;
1832 torture_comment(tctx, "BATCH16: open with batch oplock\n");
1833 ZERO_STRUCT(break_info);
1834 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1837 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1838 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1839 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1840 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1841 NTCREATEX_SHARE_ACCESS_WRITE|
1842 NTCREATEX_SHARE_ACCESS_DELETE;
1843 status = smb_raw_open(cli1->tree, tctx, &io);
1844 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1845 fnum = io.ntcreatex.out.file.fnum;
1846 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1848 ZERO_STRUCT(break_info);
1850 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
1852 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1853 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1854 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1855 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1856 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1857 NTCREATEX_SHARE_ACCESS_WRITE|
1858 NTCREATEX_SHARE_ACCESS_DELETE;
1859 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1860 status = smb_raw_open(cli2->tree, tctx, &io);
1861 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1862 fnum2 = io.ntcreatex.out.file.fnum;
1863 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1864 CHECK_VAL(break_info.count, 1);
1865 CHECK_VAL(break_info.failures, 0);
1867 smbcli_close(cli1->tree, fnum);
1868 smbcli_close(cli2->tree, fnum2);
1870 done:
1871 smb_raw_exit(cli1->session);
1872 smb_raw_exit(cli2->session);
1873 smbcli_deltree(cli1->tree, BASEDIR);
1874 return ret;
1877 static bool test_raw_oplock_batch17(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1879 const char *fname1 = BASEDIR "\\test_batch17_1.dat";
1880 const char *fname2 = BASEDIR "\\test_batch17_2.dat";
1881 NTSTATUS status;
1882 bool ret = true;
1883 union smb_open io;
1884 union smb_rename rn;
1885 uint16_t fnum=0;
1887 if (!torture_setup_dir(cli1, BASEDIR)) {
1888 return false;
1891 /* cleanup */
1892 smbcli_unlink(cli1->tree, fname1);
1893 smbcli_unlink(cli1->tree, fname2);
1895 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1898 base ntcreatex parms
1900 io.generic.level = RAW_OPEN_NTCREATEX;
1901 io.ntcreatex.in.root_fid = 0;
1902 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1903 io.ntcreatex.in.alloc_size = 0;
1904 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1905 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1906 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1907 io.ntcreatex.in.create_options = 0;
1908 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1909 io.ntcreatex.in.security_flags = 0;
1910 io.ntcreatex.in.fname = fname1;
1912 torture_comment(tctx, "BATCH17: open a file with an batch oplock (share mode: none)\n");
1914 ZERO_STRUCT(break_info);
1915 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1916 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1917 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1919 status = smb_raw_open(cli1->tree, tctx, &io);
1920 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1921 fnum = io.ntcreatex.out.file.fnum;
1922 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1924 torture_comment(tctx, "rename should trigger a break\n");
1925 ZERO_STRUCT(rn);
1926 rn.generic.level = RAW_RENAME_RENAME;
1927 rn.rename.in.pattern1 = fname1;
1928 rn.rename.in.pattern2 = fname2;
1929 rn.rename.in.attrib = 0;
1931 torture_comment(tctx, "trying rename while first file open\n");
1932 status = smb_raw_rename(cli2->tree, &rn);
1934 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1935 CHECK_VAL(break_info.count, 1);
1936 CHECK_VAL(break_info.failures, 0);
1937 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1939 smbcli_close(cli1->tree, fnum);
1941 done:
1942 smb_raw_exit(cli1->session);
1943 smb_raw_exit(cli2->session);
1944 smbcli_deltree(cli1->tree, BASEDIR);
1945 return ret;
1948 static bool test_raw_oplock_batch18(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1950 const char *fname1 = BASEDIR "\\test_batch18_1.dat";
1951 const char *fname2 = BASEDIR "\\test_batch18_2.dat";
1952 NTSTATUS status;
1953 bool ret = true;
1954 union smb_open io;
1955 union smb_rename rn;
1956 uint16_t fnum=0;
1958 if (!torture_setup_dir(cli1, BASEDIR)) {
1959 return false;
1962 /* cleanup */
1963 smbcli_unlink(cli1->tree, fname1);
1964 smbcli_unlink(cli1->tree, fname2);
1966 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1969 base ntcreatex parms
1971 io.generic.level = RAW_OPEN_NTCREATEX;
1972 io.ntcreatex.in.root_fid = 0;
1973 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1974 io.ntcreatex.in.alloc_size = 0;
1975 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1976 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1977 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1978 io.ntcreatex.in.create_options = 0;
1979 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1980 io.ntcreatex.in.security_flags = 0;
1981 io.ntcreatex.in.fname = fname1;
1983 torture_comment(tctx, "BATCH18: open a file with an batch oplock (share mode: none)\n");
1985 ZERO_STRUCT(break_info);
1986 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1987 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1988 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1990 status = smb_raw_open(cli1->tree, tctx, &io);
1991 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1992 fnum = io.ntcreatex.out.file.fnum;
1993 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1995 torture_comment(tctx, "ntrename should trigger a break\n");
1996 ZERO_STRUCT(rn);
1997 rn.generic.level = RAW_RENAME_NTRENAME;
1998 rn.ntrename.in.attrib = 0;
1999 rn.ntrename.in.flags = RENAME_FLAG_RENAME;
2000 rn.ntrename.in.old_name = fname1;
2001 rn.ntrename.in.new_name = fname2;
2002 torture_comment(tctx, "trying rename while first file open\n");
2003 status = smb_raw_rename(cli2->tree, &rn);
2005 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2006 CHECK_VAL(break_info.count, 1);
2007 CHECK_VAL(break_info.failures, 0);
2008 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2010 smbcli_close(cli1->tree, fnum);
2012 done:
2013 smb_raw_exit(cli1->session);
2014 smb_raw_exit(cli2->session);
2015 smbcli_deltree(cli1->tree, BASEDIR);
2016 return ret;
2019 static bool test_raw_oplock_batch19(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2021 const char *fname1 = BASEDIR "\\test_batch19_1.dat";
2022 const char *fname2 = BASEDIR "\\test_batch19_2.dat";
2023 const char *fname3 = BASEDIR "\\test_batch19_3.dat";
2024 NTSTATUS status;
2025 bool ret = true;
2026 union smb_open io;
2027 union smb_fileinfo qfi;
2028 union smb_setfileinfo sfi;
2029 uint16_t fnum=0;
2031 if (!torture_setup_dir(cli1, BASEDIR)) {
2032 return false;
2035 /* cleanup */
2036 smbcli_unlink(cli1->tree, fname1);
2037 smbcli_unlink(cli1->tree, fname2);
2038 smbcli_unlink(cli1->tree, fname3);
2040 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2043 base ntcreatex parms
2045 io.generic.level = RAW_OPEN_NTCREATEX;
2046 io.ntcreatex.in.root_fid = 0;
2047 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2048 io.ntcreatex.in.alloc_size = 0;
2049 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2050 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2051 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2052 io.ntcreatex.in.create_options = 0;
2053 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2054 io.ntcreatex.in.security_flags = 0;
2055 io.ntcreatex.in.fname = fname1;
2057 torture_comment(tctx, "BATCH19: open a file with an batch oplock (share mode: none)\n");
2058 ZERO_STRUCT(break_info);
2059 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2060 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2061 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2062 status = smb_raw_open(cli1->tree, tctx, &io);
2063 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2064 fnum = io.ntcreatex.out.file.fnum;
2065 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2067 torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
2068 ZERO_STRUCT(sfi);
2069 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2070 sfi.generic.in.file.path = fname1;
2071 sfi.rename_information.in.overwrite = 0;
2072 sfi.rename_information.in.root_fid = 0;
2073 sfi.rename_information.in.new_name = fname2+strlen(BASEDIR)+1;
2075 status = smb_raw_setpathinfo(cli2->tree, &sfi);
2077 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2078 CHECK_VAL(break_info.count, 0);
2080 ZERO_STRUCT(qfi);
2081 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2082 qfi.generic.in.file.fnum = fnum;
2084 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2085 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2086 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2088 torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
2089 ZERO_STRUCT(sfi);
2090 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2091 sfi.generic.in.file.fnum = fnum;
2092 sfi.rename_information.in.overwrite = 0;
2093 sfi.rename_information.in.root_fid = 0;
2094 sfi.rename_information.in.new_name = fname3+strlen(BASEDIR)+1;
2096 status = smb_raw_setfileinfo(cli1->tree, &sfi);
2097 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2098 CHECK_VAL(break_info.count, 0);
2100 ZERO_STRUCT(qfi);
2101 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2102 qfi.generic.in.file.fnum = fnum;
2104 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2105 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2106 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2108 smbcli_close(cli1->tree, fnum);
2110 done:
2111 smb_raw_exit(cli1->session);
2112 smb_raw_exit(cli2->session);
2113 smbcli_deltree(cli1->tree, BASEDIR);
2114 return ret;
2117 /****************************************************
2118 Called from raw-rename - we need oplock handling for
2119 this test so this is why it's in oplock.c, not rename.c
2120 ****************************************************/
2122 bool test_trans2rename(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2124 const char *fname1 = BASEDIR "\\test_trans2rename_1.dat";
2125 const char *fname2 = BASEDIR "\\test_trans2rename_2.dat";
2126 const char *fname3 = BASEDIR "\\test_trans2rename_3.dat";
2127 NTSTATUS status;
2128 bool ret = true;
2129 union smb_open io;
2130 union smb_fileinfo qfi;
2131 union smb_setfileinfo sfi;
2132 uint16_t fnum=0;
2134 if (!torture_setup_dir(cli1, BASEDIR)) {
2135 return false;
2138 /* cleanup */
2139 smbcli_unlink(cli1->tree, fname1);
2140 smbcli_unlink(cli1->tree, fname2);
2141 smbcli_unlink(cli1->tree, fname3);
2143 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2146 base ntcreatex parms
2148 io.generic.level = RAW_OPEN_NTCREATEX;
2149 io.ntcreatex.in.root_fid = 0;
2150 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2151 io.ntcreatex.in.alloc_size = 0;
2152 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2153 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2154 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2155 io.ntcreatex.in.create_options = 0;
2156 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2157 io.ntcreatex.in.security_flags = 0;
2158 io.ntcreatex.in.fname = fname1;
2160 torture_comment(tctx, "open a file with an exclusive oplock (share mode: none)\n");
2161 ZERO_STRUCT(break_info);
2162 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2163 NTCREATEX_FLAGS_REQUEST_OPLOCK;
2164 status = smb_raw_open(cli1->tree, tctx, &io);
2165 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2166 fnum = io.ntcreatex.out.file.fnum;
2167 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
2169 torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
2170 ZERO_STRUCT(sfi);
2171 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2172 sfi.generic.in.file.path = fname1;
2173 sfi.rename_information.in.overwrite = 0;
2174 sfi.rename_information.in.root_fid = 0;
2175 sfi.rename_information.in.new_name = fname2+strlen(BASEDIR)+1;
2177 status = smb_raw_setpathinfo(cli2->tree, &sfi);
2179 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2180 CHECK_VAL(break_info.count, 0);
2182 ZERO_STRUCT(qfi);
2183 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2184 qfi.generic.in.file.fnum = fnum;
2186 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2187 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2188 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2190 torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
2191 ZERO_STRUCT(sfi);
2192 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2193 sfi.generic.in.file.fnum = fnum;
2194 sfi.rename_information.in.overwrite = 0;
2195 sfi.rename_information.in.root_fid = 0;
2196 sfi.rename_information.in.new_name = fname3+strlen(BASEDIR)+1;
2198 status = smb_raw_setfileinfo(cli1->tree, &sfi);
2199 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2200 CHECK_VAL(break_info.count, 0);
2202 ZERO_STRUCT(qfi);
2203 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2204 qfi.generic.in.file.fnum = fnum;
2206 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2207 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2208 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2210 smbcli_close(cli1->tree, fnum);
2212 done:
2213 smb_raw_exit(cli1->session);
2214 smb_raw_exit(cli2->session);
2215 smbcli_deltree(cli1->tree, BASEDIR);
2216 return ret;
2219 /****************************************************
2220 Called from raw-rename - we need oplock handling for
2221 this test so this is why it's in oplock.c, not rename.c
2222 ****************************************************/
2224 bool test_nttransrename(struct torture_context *tctx, struct smbcli_state *cli1)
2226 const char *fname1 = BASEDIR "\\test_nttransrename_1.dat";
2227 const char *fname2 = BASEDIR "\\test_nttransrename_2.dat";
2228 NTSTATUS status;
2229 bool ret = true;
2230 union smb_open io;
2231 union smb_fileinfo qfi, qpi;
2232 union smb_rename rn;
2233 uint16_t fnum=0;
2235 if (!torture_setup_dir(cli1, BASEDIR)) {
2236 return false;
2239 /* cleanup */
2240 smbcli_unlink(cli1->tree, fname1);
2241 smbcli_unlink(cli1->tree, fname2);
2243 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2246 base ntcreatex parms
2248 io.generic.level = RAW_OPEN_NTCREATEX;
2249 io.ntcreatex.in.root_fid = 0;
2250 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2251 io.ntcreatex.in.alloc_size = 0;
2252 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2253 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2254 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2255 io.ntcreatex.in.create_options = 0;
2256 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2257 io.ntcreatex.in.security_flags = 0;
2258 io.ntcreatex.in.fname = fname1;
2260 torture_comment(tctx, "nttrans_rename: open a file with an exclusive oplock (share mode: none)\n");
2261 ZERO_STRUCT(break_info);
2262 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2263 NTCREATEX_FLAGS_REQUEST_OPLOCK;
2264 status = smb_raw_open(cli1->tree, tctx, &io);
2265 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2266 fnum = io.ntcreatex.out.file.fnum;
2267 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
2269 torture_comment(tctx, "nttrans_rename: should not trigger a break nor a share mode violation\n");
2270 ZERO_STRUCT(rn);
2271 rn.generic.level = RAW_RENAME_NTTRANS;
2272 rn.nttrans.in.file.fnum = fnum;
2273 rn.nttrans.in.flags = 0;
2274 rn.nttrans.in.new_name = fname2+strlen(BASEDIR)+1;
2276 status = smb_raw_rename(cli1->tree, &rn);
2278 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2279 CHECK_VAL(break_info.count, 0);
2281 /* w2k3 does nothing, it doesn't rename the file */
2282 torture_comment(tctx, "nttrans_rename: the server should have done nothing\n");
2283 ZERO_STRUCT(qfi);
2284 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2285 qfi.generic.in.file.fnum = fnum;
2287 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2288 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2289 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname1);
2291 ZERO_STRUCT(qpi);
2292 qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2293 qpi.generic.in.file.path = fname1;
2295 status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2296 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2297 CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1);
2299 ZERO_STRUCT(qpi);
2300 qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2301 qpi.generic.in.file.path = fname2;
2303 status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2304 CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2306 torture_comment(tctx, "nttrans_rename: after closing the file the file is still not renamed\n");
2307 status = smbcli_close(cli1->tree, fnum);
2308 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2310 ZERO_STRUCT(qpi);
2311 qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2312 qpi.generic.in.file.path = fname1;
2314 status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2315 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2316 CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1);
2318 ZERO_STRUCT(qpi);
2319 qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2320 qpi.generic.in.file.path = fname2;
2322 status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2323 CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2325 torture_comment(tctx, "nttrans_rename: rename with an invalid handle gives NT_STATUS_INVALID_HANDLE\n");
2326 ZERO_STRUCT(rn);
2327 rn.generic.level = RAW_RENAME_NTTRANS;
2328 rn.nttrans.in.file.fnum = fnum+1;
2329 rn.nttrans.in.flags = 0;
2330 rn.nttrans.in.new_name = fname2+strlen(BASEDIR)+1;
2332 status = smb_raw_rename(cli1->tree, &rn);
2334 CHECK_STATUS(tctx, status, NT_STATUS_INVALID_HANDLE);
2336 done:
2337 smb_raw_exit(cli1->session);
2338 smbcli_deltree(cli1->tree, BASEDIR);
2339 return ret;
2343 static bool test_raw_oplock_batch20(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2345 const char *fname1 = BASEDIR "\\test_batch20_1.dat";
2346 const char *fname2 = BASEDIR "\\test_batch20_2.dat";
2347 const char *fname3 = BASEDIR "\\test_batch20_3.dat";
2348 NTSTATUS status;
2349 bool ret = true;
2350 union smb_open io;
2351 union smb_fileinfo qfi;
2352 union smb_setfileinfo sfi;
2353 uint16_t fnum=0,fnum2=0;
2355 if (!torture_setup_dir(cli1, BASEDIR)) {
2356 return false;
2359 /* cleanup */
2360 smbcli_unlink(cli1->tree, fname1);
2361 smbcli_unlink(cli1->tree, fname2);
2362 smbcli_unlink(cli1->tree, fname3);
2364 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2367 base ntcreatex parms
2369 io.generic.level = RAW_OPEN_NTCREATEX;
2370 io.ntcreatex.in.root_fid = 0;
2371 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2372 io.ntcreatex.in.alloc_size = 0;
2373 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2374 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2375 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2376 io.ntcreatex.in.create_options = 0;
2377 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2378 io.ntcreatex.in.security_flags = 0;
2379 io.ntcreatex.in.fname = fname1;
2381 torture_comment(tctx, "BATCH20: open a file with an batch oplock (share mode: all)\n");
2382 ZERO_STRUCT(break_info);
2383 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2384 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2385 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2386 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2387 NTCREATEX_SHARE_ACCESS_WRITE|
2388 NTCREATEX_SHARE_ACCESS_DELETE;
2389 status = smb_raw_open(cli1->tree, tctx, &io);
2390 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2391 fnum = io.ntcreatex.out.file.fnum;
2392 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2394 torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
2395 ZERO_STRUCT(sfi);
2396 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2397 sfi.generic.in.file.path = fname1;
2398 sfi.rename_information.in.overwrite = 0;
2399 sfi.rename_information.in.root_fid = 0;
2400 sfi.rename_information.in.new_name = fname2+strlen(BASEDIR)+1;
2402 status = smb_raw_setpathinfo(cli2->tree, &sfi);
2404 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2405 CHECK_VAL(break_info.count, 0);
2407 ZERO_STRUCT(qfi);
2408 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2409 qfi.generic.in.file.fnum = fnum;
2411 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2412 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2413 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2415 torture_comment(tctx, "open a file with the new name an batch oplock (share mode: all)\n");
2416 ZERO_STRUCT(break_info);
2417 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2418 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2419 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2420 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2421 NTCREATEX_SHARE_ACCESS_WRITE|
2422 NTCREATEX_SHARE_ACCESS_DELETE;
2423 io.ntcreatex.in.fname = fname2;
2424 status = smb_raw_open(cli2->tree, tctx, &io);
2425 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2426 fnum2 = io.ntcreatex.out.file.fnum;
2427 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2428 CHECK_VAL(break_info.count, 1);
2429 CHECK_VAL(break_info.failures, 0);
2430 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2432 torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
2433 ZERO_STRUCT(sfi);
2434 sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2435 sfi.generic.in.file.fnum = fnum;
2436 sfi.rename_information.in.overwrite = 0;
2437 sfi.rename_information.in.root_fid = 0;
2438 sfi.rename_information.in.new_name = fname3+strlen(BASEDIR)+1;
2440 status = smb_raw_setfileinfo(cli1->tree, &sfi);
2441 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2442 CHECK_VAL(break_info.count, 1);
2443 CHECK_VAL(break_info.failures, 0);
2444 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2446 ZERO_STRUCT(qfi);
2447 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2448 qfi.generic.in.file.fnum = fnum;
2450 status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2451 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2452 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2454 ZERO_STRUCT(qfi);
2455 qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2456 qfi.generic.in.file.fnum = fnum2;
2458 status = smb_raw_fileinfo(cli2->tree, tctx, &qfi);
2459 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2460 CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2462 smbcli_close(cli1->tree, fnum);
2464 done:
2465 smb_raw_exit(cli1->session);
2466 smb_raw_exit(cli2->session);
2467 smbcli_deltree(cli1->tree, BASEDIR);
2468 return ret;
2471 static bool test_raw_oplock_batch21(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2473 const char *fname = BASEDIR "\\test_batch21.dat";
2474 NTSTATUS status;
2475 bool ret = true;
2476 union smb_open io;
2477 struct smb_echo e;
2478 uint16_t fnum=0;
2479 char c = 0;
2480 ssize_t wr;
2482 if (!torture_setup_dir(cli1, BASEDIR)) {
2483 return false;
2486 /* cleanup */
2487 smbcli_unlink(cli1->tree, fname);
2489 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2492 base ntcreatex parms
2494 io.generic.level = RAW_OPEN_NTCREATEX;
2495 io.ntcreatex.in.root_fid = 0;
2496 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2497 io.ntcreatex.in.alloc_size = 0;
2498 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2499 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2500 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2501 io.ntcreatex.in.create_options = 0;
2502 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2503 io.ntcreatex.in.security_flags = 0;
2504 io.ntcreatex.in.fname = fname;
2507 with a batch oplock we get a break
2509 torture_comment(tctx, "BATCH21: open with batch oplock\n");
2510 ZERO_STRUCT(break_info);
2511 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2512 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2513 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2514 status = smb_raw_open(cli1->tree, tctx, &io);
2515 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2516 fnum = io.ntcreatex.out.file.fnum;
2517 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2519 torture_comment(tctx, "writing should not generate a break\n");
2520 wr = smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
2521 CHECK_VAL(wr, 1);
2522 CHECK_STATUS(tctx, smbcli_nt_error(cli1->tree), NT_STATUS_OK);
2524 ZERO_STRUCT(e);
2525 e.in.repeat_count = 1;
2526 status = smb_raw_echo(cli1->transport, &e);
2527 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2529 CHECK_VAL(break_info.count, 0);
2531 smbcli_close(cli1->tree, fnum);
2533 done:
2534 smb_raw_exit(cli1->session);
2535 smb_raw_exit(cli2->session);
2536 smbcli_deltree(cli1->tree, BASEDIR);
2537 return ret;
2540 static bool test_raw_oplock_batch22(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2542 const char *fname = BASEDIR "\\test_batch22.dat";
2543 NTSTATUS status;
2544 bool ret = true;
2545 union smb_open io;
2546 uint16_t fnum=0, fnum2=0;
2547 struct timeval tv;
2548 int timeout = torture_setting_int(tctx, "oplocktimeout", 30);
2549 int te;
2551 if (torture_setting_bool(tctx, "samba3", false)) {
2552 torture_skip(tctx, "BATCH22 disabled against samba3\n");
2555 if (!torture_setup_dir(cli1, BASEDIR)) {
2556 return false;
2559 /* cleanup */
2560 smbcli_unlink(cli1->tree, fname);
2562 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2565 base ntcreatex parms
2567 io.generic.level = RAW_OPEN_NTCREATEX;
2568 io.ntcreatex.in.root_fid = 0;
2569 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2570 io.ntcreatex.in.alloc_size = 0;
2571 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2572 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2573 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2574 io.ntcreatex.in.create_options = 0;
2575 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2576 io.ntcreatex.in.security_flags = 0;
2577 io.ntcreatex.in.fname = fname;
2580 with a batch oplock we get a break
2582 torture_comment(tctx, "BATCH22: open with batch oplock\n");
2583 ZERO_STRUCT(break_info);
2584 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2585 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2586 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2587 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2588 NTCREATEX_SHARE_ACCESS_WRITE|
2589 NTCREATEX_SHARE_ACCESS_DELETE;
2590 status = smb_raw_open(cli1->tree, tctx, &io);
2591 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2592 fnum = io.ntcreatex.out.file.fnum;
2593 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2595 torture_comment(tctx, "a 2nd open shoud not succeed after the oplock break timeout\n");
2596 tv = timeval_current();
2597 smbcli_oplock_handler(cli1->transport, oplock_handler_timeout, cli1->tree);
2598 status = smb_raw_open(cli1->tree, tctx, &io);
2599 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2600 te = (int)timeval_elapsed(&tv);
2601 CHECK_RANGE(te, timeout - 1, timeout + 15);
2603 CHECK_VAL(break_info.count, 1);
2604 CHECK_VAL(break_info.fnum, fnum);
2605 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2606 CHECK_VAL(break_info.failures, 0);
2607 ZERO_STRUCT(break_info);
2609 torture_comment(tctx, "a 2nd open shoud succeed after the oplock release without break\n");
2610 tv = timeval_current();
2611 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2612 status = smb_raw_open(cli1->tree, tctx, &io);
2613 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2614 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2615 te = (int)timeval_elapsed(&tv);
2616 /* it should come in without delay */
2617 CHECK_RANGE(te+1, 0, timeout);
2618 fnum2 = io.ntcreatex.out.file.fnum;
2620 CHECK_VAL(break_info.count, 0);
2622 smbcli_close(cli1->tree, fnum);
2623 smbcli_close(cli1->tree, fnum2);
2625 done:
2626 smb_raw_exit(cli1->session);
2627 smb_raw_exit(cli2->session);
2628 smbcli_deltree(cli1->tree, BASEDIR);
2629 return ret;
2632 static bool test_raw_oplock_batch23(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2634 const char *fname = BASEDIR "\\test_batch23.dat";
2635 NTSTATUS status;
2636 bool ret = true;
2637 union smb_open io;
2638 uint16_t fnum=0, fnum2=0,fnum3=0;
2639 struct smbcli_state *cli3 = NULL;
2641 if (!torture_setup_dir(cli1, BASEDIR)) {
2642 return false;
2645 /* cleanup */
2646 smbcli_unlink(cli1->tree, fname);
2648 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2650 ret = open_connection_no_level2_oplocks(tctx, &cli3);
2651 CHECK_VAL(ret, true);
2654 base ntcreatex parms
2656 io.generic.level = RAW_OPEN_NTCREATEX;
2657 io.ntcreatex.in.root_fid = 0;
2658 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2659 io.ntcreatex.in.alloc_size = 0;
2660 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2661 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2662 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2663 io.ntcreatex.in.create_options = 0;
2664 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2665 io.ntcreatex.in.security_flags = 0;
2666 io.ntcreatex.in.fname = fname;
2668 torture_comment(tctx, "BATCH23: a open and ask for a batch oplock\n");
2669 ZERO_STRUCT(break_info);
2670 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2671 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
2672 smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
2674 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
2675 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
2676 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2677 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2678 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2679 status = smb_raw_open(cli1->tree, tctx, &io);
2680 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2681 fnum = io.ntcreatex.out.file.fnum;
2682 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2684 ZERO_STRUCT(break_info);
2686 torture_comment(tctx, "a 2nd open without level2 oplock support should generate a break to level2\n");
2687 status = smb_raw_open(cli3->tree, tctx, &io);
2688 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2689 fnum3 = io.ntcreatex.out.file.fnum;
2690 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
2692 CHECK_VAL(break_info.count, 1);
2693 CHECK_VAL(break_info.fnum, fnum);
2694 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2695 CHECK_VAL(break_info.failures, 0);
2697 ZERO_STRUCT(break_info);
2699 torture_comment(tctx, "a 3rd open with level2 oplock support should not generate a break\n");
2700 status = smb_raw_open(cli2->tree, tctx, &io);
2701 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2702 fnum2 = io.ntcreatex.out.file.fnum;
2703 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2705 CHECK_VAL(break_info.count, 0);
2707 smbcli_close(cli1->tree, fnum);
2708 smbcli_close(cli2->tree, fnum2);
2709 smbcli_close(cli3->tree, fnum3);
2711 done:
2712 smb_raw_exit(cli1->session);
2713 smb_raw_exit(cli2->session);
2714 smb_raw_exit(cli3->session);
2715 smbcli_deltree(cli1->tree, BASEDIR);
2716 return ret;
2719 static bool test_raw_oplock_batch24(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2721 const char *fname = BASEDIR "\\test_batch24.dat";
2722 NTSTATUS status;
2723 bool ret = true;
2724 union smb_open io;
2725 uint16_t fnum2=0,fnum3=0;
2726 struct smbcli_state *cli3 = NULL;
2728 if (!torture_setup_dir(cli1, BASEDIR)) {
2729 return false;
2732 /* cleanup */
2733 smbcli_unlink(cli1->tree, fname);
2735 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2737 ret = open_connection_no_level2_oplocks(tctx, &cli3);
2738 CHECK_VAL(ret, true);
2741 base ntcreatex parms
2743 io.generic.level = RAW_OPEN_NTCREATEX;
2744 io.ntcreatex.in.root_fid = 0;
2745 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2746 io.ntcreatex.in.alloc_size = 0;
2747 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2748 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2749 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2750 io.ntcreatex.in.create_options = 0;
2751 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2752 io.ntcreatex.in.security_flags = 0;
2753 io.ntcreatex.in.fname = fname;
2755 torture_comment(tctx, "BATCH24: a open without level support and ask for a batch oplock\n");
2756 ZERO_STRUCT(break_info);
2757 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2758 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
2759 smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
2761 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
2762 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
2763 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2764 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2765 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2766 status = smb_raw_open(cli3->tree, tctx, &io);
2767 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2768 fnum3 = io.ntcreatex.out.file.fnum;
2769 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2771 ZERO_STRUCT(break_info);
2773 torture_comment(tctx, "a 2nd open with level2 oplock support should generate a break to none\n");
2774 status = smb_raw_open(cli2->tree, tctx, &io);
2775 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2776 fnum2 = io.ntcreatex.out.file.fnum;
2777 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2779 CHECK_VAL(break_info.count, 1);
2780 CHECK_VAL(break_info.fnum, fnum3);
2781 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
2782 CHECK_VAL(break_info.failures, 0);
2784 smbcli_close(cli3->tree, fnum3);
2785 smbcli_close(cli2->tree, fnum2);
2787 done:
2788 smb_raw_exit(cli1->session);
2789 smb_raw_exit(cli2->session);
2790 smb_raw_exit(cli3->session);
2791 smbcli_deltree(cli1->tree, BASEDIR);
2792 return ret;
2795 static bool test_raw_oplock_batch25(struct torture_context *tctx,
2796 struct smbcli_state *cli1,
2797 struct smbcli_state *cli2)
2799 const char *fname = BASEDIR "\\test_batch25.dat";
2800 NTSTATUS status;
2801 bool ret = true;
2802 union smb_open io;
2803 union smb_setfileinfo sfi;
2804 uint16_t fnum=0;
2806 if (!torture_setup_dir(cli1, BASEDIR)) {
2807 return false;
2810 /* cleanup */
2811 smbcli_unlink(cli1->tree, fname);
2813 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2816 base ntcreatex parms
2818 io.generic.level = RAW_OPEN_NTCREATEX;
2819 io.ntcreatex.in.root_fid = 0;
2820 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2821 io.ntcreatex.in.alloc_size = 0;
2822 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2823 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2824 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2825 io.ntcreatex.in.create_options = 0;
2826 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2827 io.ntcreatex.in.security_flags = 0;
2828 io.ntcreatex.in.fname = fname;
2830 torture_comment(tctx, "BATCH25: open a file with an batch oplock "
2831 "(share mode: none)\n");
2833 ZERO_STRUCT(break_info);
2834 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2835 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2836 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2837 status = smb_raw_open(cli1->tree, tctx, &io);
2838 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2839 fnum = io.ntcreatex.out.file.fnum;
2840 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2842 torture_comment(tctx, "setpathinfo attribute info should not trigger "
2843 "a break nor a violation\n");
2844 ZERO_STRUCT(sfi);
2845 sfi.generic.level = RAW_SFILEINFO_SETATTR;
2846 sfi.generic.in.file.path = fname;
2847 sfi.setattr.in.attrib = FILE_ATTRIBUTE_HIDDEN;
2848 sfi.setattr.in.write_time = 0;
2850 status = smb_raw_setpathinfo(cli2->tree, &sfi);
2852 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2853 CHECK_VAL(break_info.count, 0);
2855 smbcli_close(cli1->tree, fnum);
2857 done:
2858 smb_raw_exit(cli1->session);
2859 smb_raw_exit(cli2->session);
2860 smbcli_deltree(cli1->tree, BASEDIR);
2861 return ret;
2864 /* Test how oplocks work on streams. */
2865 static bool test_raw_oplock_stream1(struct torture_context *tctx,
2866 struct smbcli_state *cli1,
2867 struct smbcli_state *cli2)
2869 NTSTATUS status;
2870 union smb_open io;
2871 const char *fname_base = BASEDIR "\\test_stream1.txt";
2872 const char *stream = "Stream One:$DATA";
2873 const char *fname_stream, *fname_default_stream;
2874 const char *default_stream = "::$DATA";
2875 bool ret = true;
2876 int fnum = -1;
2877 int i;
2878 int stream_fnum = -1;
2879 uint32_t batch_req = NTCREATEX_FLAGS_REQUEST_OPLOCK |
2880 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK | NTCREATEX_FLAGS_EXTENDED;
2881 uint32_t exclusive_req = NTCREATEX_FLAGS_REQUEST_OPLOCK |
2882 NTCREATEX_FLAGS_EXTENDED;
2883 /* Try some permutations of taking oplocks on streams. */
2884 #define NSTREAM_OPLOCK_RESULTS 8
2885 struct {
2886 const char *fname;
2887 bool open_base_file;
2888 uint32_t oplock_req;
2889 uint32_t oplock_granted;
2890 } stream_oplock_results[NSTREAM_OPLOCK_RESULTS] = {
2891 /* Request oplock on stream without the base file open. */
2892 {fname_stream, false, batch_req, NO_OPLOCK_RETURN},
2893 {fname_default_stream, false, batch_req, NO_OPLOCK_RETURN},
2894 {fname_stream, false, exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
2895 {fname_default_stream, false, exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
2897 /* Request oplock on stream with the base file open. */
2898 {fname_stream, true, batch_req, NO_OPLOCK_RETURN},
2899 {fname_default_stream, true, batch_req, NO_OPLOCK_RETURN},
2900 {fname_stream, true, exclusive_req, EXCLUSIVE_OPLOCK_RETURN},
2901 {fname_default_stream, true, exclusive_req, LEVEL_II_OPLOCK_RETURN},
2906 /* Only passes against windows at the moment. */
2907 if (torture_setting_bool(tctx, "samba3", false) ||
2908 torture_setting_bool(tctx, "samba4", false)) {
2909 torture_skip(tctx, "STREAM1 disabled against samba3+4\n");
2912 fname_stream = talloc_asprintf(tctx, "%s:%s", fname_base, stream);
2913 fname_default_stream = talloc_asprintf(tctx, "%s%s", fname_base,
2914 default_stream);
2916 if (!torture_setup_dir(cli1, BASEDIR)) {
2917 return false;
2919 smbcli_unlink(cli1->tree, fname_base);
2921 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
2922 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2924 /* Setup generic open parameters. */
2925 io.generic.level = RAW_OPEN_NTCREATEX;
2926 io.ntcreatex.in.root_fid = 0;
2927 io.ntcreatex.in.access_mask = (SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA|
2928 SEC_FILE_APPEND_DATA|SEC_STD_READ_CONTROL);
2929 io.ntcreatex.in.create_options = 0;
2930 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2931 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2932 NTCREATEX_SHARE_ACCESS_WRITE;
2933 io.ntcreatex.in.alloc_size = 0;
2934 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2935 io.ntcreatex.in.security_flags = 0;
2937 /* Create the file with a stream */
2938 io.ntcreatex.in.fname = fname_stream;
2939 io.ntcreatex.in.flags = 0;
2940 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2941 status = smb_raw_open(cli1->tree, tctx, &io);
2942 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2943 smbcli_close(cli1->tree, io.ntcreatex.out.file.fnum);
2945 /* Change the disposition to open now that the file has been created. */
2946 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
2948 for (i = 0; i < NSTREAM_OPLOCK_RESULTS; i++) {
2949 const char *fname = stream_oplock_results[i].fname;
2950 bool open_base_file = stream_oplock_results[i].open_base_file;
2951 uint32_t oplock_req = stream_oplock_results[i].oplock_req;
2952 uint32_t oplock_granted =
2953 stream_oplock_results[i].oplock_granted;
2954 int base_fnum = -1;
2956 if (open_base_file) {
2957 torture_comment(tctx, "Opening base file: %s with "
2958 "%d\n", fname_base, oplock_req);
2959 io.ntcreatex.in.fname = fname_base;
2960 io.ntcreatex.in.flags = batch_req;
2961 status = smb_raw_open(cli2->tree, tctx, &io);
2962 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2963 CHECK_VAL(io.ntcreatex.out.oplock_level,
2964 BATCH_OPLOCK_RETURN);
2965 base_fnum = io.ntcreatex.out.file.fnum;
2968 torture_comment(tctx, "%d: Opening stream: %s with %d\n", i,
2969 fname, oplock_req);
2970 io.ntcreatex.in.fname = fname;
2971 io.ntcreatex.in.flags = oplock_req;
2973 /* Do the open with the desired oplock on the stream. */
2974 status = smb_raw_open(cli1->tree, tctx, &io);
2975 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2976 CHECK_VAL(io.ntcreatex.out.oplock_level, oplock_granted);
2977 smbcli_close(cli1->tree, io.ntcreatex.out.file.fnum);
2979 /* Cleanup the base file if it was opened. */
2980 if (base_fnum != -1) {
2981 smbcli_close(cli2->tree, base_fnum);
2985 /* Open the stream with an exclusive oplock. */
2986 torture_comment(tctx, "Opening stream: %s with %d\n",
2987 fname_stream, exclusive_req);
2988 io.ntcreatex.in.fname = fname_stream;
2989 io.ntcreatex.in.flags = exclusive_req;
2990 status = smb_raw_open(cli1->tree, tctx, &io);
2991 CHECK_STATUS(tctx, status, NT_STATUS_OK);
2992 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
2993 stream_fnum = io.ntcreatex.out.file.fnum;
2995 /* Open the base file and see if it contends. */
2996 ZERO_STRUCT(break_info);
2997 torture_comment(tctx, "Opening base file: %s with "
2998 "%d\n", fname_base, batch_req);
2999 io.ntcreatex.in.fname = fname_base;
3000 io.ntcreatex.in.flags = batch_req;
3001 status = smb_raw_open(cli2->tree, tctx, &io);
3002 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3003 CHECK_VAL(io.ntcreatex.out.oplock_level,
3004 BATCH_OPLOCK_RETURN);
3005 smbcli_close(cli2->tree, io.ntcreatex.out.file.fnum);
3007 CHECK_VAL(break_info.count, 0);
3008 CHECK_VAL(break_info.failures, 0);
3010 /* Open the stream again to see if it contends. */
3011 ZERO_STRUCT(break_info);
3012 torture_comment(tctx, "Opening stream again: %s with "
3013 "%d\n", fname_base, batch_req);
3014 io.ntcreatex.in.fname = fname_stream;
3015 io.ntcreatex.in.flags = exclusive_req;
3016 status = smb_raw_open(cli2->tree, tctx, &io);
3017 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3018 CHECK_VAL(io.ntcreatex.out.oplock_level,
3019 LEVEL_II_OPLOCK_RETURN);
3020 smbcli_close(cli2->tree, io.ntcreatex.out.file.fnum);
3022 CHECK_VAL(break_info.count, 1);
3023 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3024 CHECK_VAL(break_info.failures, 0);
3026 /* Close the stream. */
3027 if (stream_fnum != -1) {
3028 smbcli_close(cli1->tree, stream_fnum);
3031 done:
3032 smbcli_close(cli1->tree, fnum);
3033 smb_raw_exit(cli1->session);
3034 smb_raw_exit(cli2->session);
3035 smbcli_deltree(cli1->tree, BASEDIR);
3036 return ret;
3039 static bool test_raw_oplock_doc(struct torture_context *tctx,
3040 struct smbcli_state *cli)
3042 const char *fname = BASEDIR "\\test_oplock_doc.dat";
3043 NTSTATUS status;
3044 bool ret = true;
3045 union smb_open io;
3046 uint16_t fnum=0;
3048 if (!torture_setup_dir(cli, BASEDIR)) {
3049 return false;
3052 /* cleanup */
3053 smbcli_unlink(cli->tree, fname);
3055 smbcli_oplock_handler(cli->transport, oplock_handler_ack_to_given,
3056 cli->tree);
3059 base ntcreatex parms
3061 io.generic.level = RAW_OPEN_NTCREATEX;
3062 io.ntcreatex.in.root_fid = 0;
3063 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3064 io.ntcreatex.in.alloc_size = 0;
3065 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3066 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3067 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3068 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
3069 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3070 io.ntcreatex.in.security_flags = 0;
3071 io.ntcreatex.in.fname = fname;
3073 torture_comment(tctx, "open a delete-on-close file with a batch "
3074 "oplock\n");
3075 ZERO_STRUCT(break_info);
3076 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3077 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3078 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3080 status = smb_raw_open(cli->tree, tctx, &io);
3081 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3082 fnum = io.ntcreatex.out.file.fnum;
3083 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3085 smbcli_close(cli->tree, fnum);
3087 done:
3088 smb_raw_exit(cli->session);
3089 smbcli_deltree(cli->tree, BASEDIR);
3090 return ret;
3093 /* Open a file with a batch oplock, then open it again from a second client
3094 * requesting no oplock. Having two open file handles should break our own
3095 * oplock during BRL acquisition.
3097 static bool test_raw_oplock_brl1(struct torture_context *tctx,
3098 struct smbcli_state *cli1,
3099 struct smbcli_state *cli2)
3101 const char *fname = BASEDIR "\\test_batch_brl.dat";
3102 /*int fname, f;*/
3103 bool ret = true;
3104 uint8_t buf[1000];
3105 bool correct = true;
3106 union smb_open io;
3107 NTSTATUS status;
3108 uint16_t fnum=0;
3109 uint16_t fnum2=0;
3111 if (!torture_setup_dir(cli1, BASEDIR)) {
3112 return false;
3115 /* cleanup */
3116 smbcli_unlink(cli1->tree, fname);
3118 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3119 cli1->tree);
3122 base ntcreatex parms
3124 io.generic.level = RAW_OPEN_NTCREATEX;
3125 io.ntcreatex.in.root_fid = 0;
3126 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3127 SEC_RIGHTS_FILE_WRITE;
3128 io.ntcreatex.in.alloc_size = 0;
3129 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3130 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3131 NTCREATEX_SHARE_ACCESS_WRITE;
3132 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3133 io.ntcreatex.in.create_options = 0;
3134 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3135 io.ntcreatex.in.security_flags = 0;
3136 io.ntcreatex.in.fname = fname;
3139 with a batch oplock we get a break
3141 torture_comment(tctx, "open with batch oplock\n");
3142 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3143 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3144 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3146 status = smb_raw_open(cli1->tree, tctx, &io);
3147 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3148 fnum = io.ntcreatex.out.file.fnum;
3149 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3150 /* create a file with bogus data */
3151 memset(buf, 0, sizeof(buf));
3153 if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
3154 sizeof(buf))
3156 torture_comment(tctx, "Failed to create file\n");
3157 correct = false;
3158 goto done;
3161 torture_comment(tctx, "a 2nd open should give a break\n");
3162 ZERO_STRUCT(break_info);
3163 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3164 cli1->tree);
3166 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
3167 status = smb_raw_open(cli2->tree, tctx, &io);
3168 fnum2 = io.ntcreatex.out.file.fnum;
3169 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3170 CHECK_VAL(break_info.count, 1);
3171 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3172 CHECK_VAL(break_info.failures, 0);
3173 CHECK_VAL(break_info.fnum, fnum);
3175 ZERO_STRUCT(break_info);
3176 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3177 cli1->tree);
3179 torture_comment(tctx, "attempt BRL test\n");
3181 status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
3182 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3185 * Even though level 2 oplock breaks are asynchronous, with self
3186 * contention we'll always break the oplock before the contending
3187 * operation's response is sent.
3189 CHECK_VAL(break_info.count, 1);
3190 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
3191 CHECK_VAL(break_info.fnum, fnum);
3192 CHECK_VAL(break_info.failures, 0);
3194 /* expect no oplock break */
3195 ZERO_STRUCT(break_info);
3196 status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
3197 CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
3199 CHECK_VAL(break_info.count, 0);
3200 CHECK_VAL(break_info.level, 0);
3201 CHECK_VAL(break_info.fnum, 0);
3202 CHECK_VAL(break_info.failures, 0);
3204 smbcli_close(cli1->tree, fnum);
3205 smbcli_close(cli2->tree, fnum2);
3207 done:
3208 smb_raw_exit(cli1->session);
3209 smb_raw_exit(cli2->session);
3210 smbcli_deltree(cli1->tree, BASEDIR);
3211 return ret;
3215 /* Open a file with a batch oplock on one client and then acquire a brl.
3216 * We should not contend our own oplock.
3218 static bool test_raw_oplock_brl2(struct torture_context *tctx, struct smbcli_state *cli1)
3220 const char *fname = BASEDIR "\\test_batch_brl.dat";
3221 /*int fname, f;*/
3222 bool ret = true;
3223 uint8_t buf[1000];
3224 bool correct = true;
3225 union smb_open io;
3226 NTSTATUS status;
3227 uint16_t fnum=0;
3229 if (!torture_setup_dir(cli1, BASEDIR)) {
3230 return false;
3233 /* cleanup */
3234 smbcli_unlink(cli1->tree, fname);
3236 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3237 cli1->tree);
3240 base ntcreatex parms
3242 io.generic.level = RAW_OPEN_NTCREATEX;
3243 io.ntcreatex.in.root_fid = 0;
3244 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3245 SEC_RIGHTS_FILE_WRITE;
3246 io.ntcreatex.in.alloc_size = 0;
3247 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3248 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3249 NTCREATEX_SHARE_ACCESS_WRITE;
3250 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3251 io.ntcreatex.in.create_options = 0;
3252 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3253 io.ntcreatex.in.security_flags = 0;
3254 io.ntcreatex.in.fname = fname;
3257 with a batch oplock we get a break
3259 torture_comment(tctx, "open with batch oplock\n");
3260 ZERO_STRUCT(break_info);
3261 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3262 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3263 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3265 status = smb_raw_open(cli1->tree, tctx, &io);
3266 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3267 fnum = io.ntcreatex.out.file.fnum;
3268 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3270 /* create a file with bogus data */
3271 memset(buf, 0, sizeof(buf));
3273 if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
3274 sizeof(buf))
3276 torture_comment(tctx, "Failed to create file\n");
3277 correct = false;
3278 goto done;
3281 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3282 cli1->tree);
3284 torture_comment(tctx, "attempt BRL test\n");
3286 status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
3287 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3289 status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
3290 CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
3292 /* With one file handle open a BRL should not contend our oplock.
3293 * Thus, no oplock break will be received and the entire break_info
3294 * struct will be 0 */
3295 CHECK_VAL(break_info.fnum, 0);
3296 CHECK_VAL(break_info.count, 0);
3297 CHECK_VAL(break_info.level, 0);
3298 CHECK_VAL(break_info.failures, 0);
3300 smbcli_close(cli1->tree, fnum);
3302 done:
3303 smb_raw_exit(cli1->session);
3304 smbcli_deltree(cli1->tree, BASEDIR);
3305 return ret;
3308 /* Open a file with a batch oplock twice from one client and then acquire a
3309 * brl. BRL acquisition should break our own oplock.
3311 static bool test_raw_oplock_brl3(struct torture_context *tctx,
3312 struct smbcli_state *cli1)
3314 const char *fname = BASEDIR "\\test_batch_brl.dat";
3315 bool ret = true;
3316 uint8_t buf[1000];
3317 bool correct = true;
3318 union smb_open io;
3319 NTSTATUS status;
3320 uint16_t fnum=0;
3321 uint16_t fnum2=0;
3323 if (!torture_setup_dir(cli1, BASEDIR)) {
3324 return false;
3327 /* cleanup */
3328 smbcli_unlink(cli1->tree, fname);
3330 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3331 cli1->tree);
3334 base ntcreatex parms
3336 io.generic.level = RAW_OPEN_NTCREATEX;
3337 io.ntcreatex.in.root_fid = 0;
3338 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
3339 SEC_RIGHTS_FILE_WRITE;
3340 io.ntcreatex.in.alloc_size = 0;
3341 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3342 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3343 NTCREATEX_SHARE_ACCESS_WRITE;
3344 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3345 io.ntcreatex.in.create_options = 0;
3346 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3347 io.ntcreatex.in.security_flags = 0;
3348 io.ntcreatex.in.fname = fname;
3351 with a batch oplock we get a break
3353 torture_comment(tctx, "open with batch oplock\n");
3354 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3355 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3356 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3358 status = smb_raw_open(cli1->tree, tctx, &io);
3359 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3360 fnum = io.ntcreatex.out.file.fnum;
3361 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
3363 /* create a file with bogus data */
3364 memset(buf, 0, sizeof(buf));
3366 if (smbcli_write(cli1->tree, fnum, 0, buf, 0, sizeof(buf)) !=
3367 sizeof(buf))
3369 torture_comment(tctx, "Failed to create file\n");
3370 correct = false;
3371 goto done;
3374 torture_comment(tctx, "a 2nd open should give a break\n");
3375 ZERO_STRUCT(break_info);
3376 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3377 cli1->tree);
3379 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
3380 status = smb_raw_open(cli1->tree, tctx, &io);
3381 fnum2 = io.ntcreatex.out.file.fnum;
3382 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3383 CHECK_VAL(break_info.count, 1);
3384 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
3385 CHECK_VAL(break_info.failures, 0);
3386 CHECK_VAL(break_info.fnum, fnum);
3388 ZERO_STRUCT(break_info);
3389 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given,
3390 cli1->tree);
3392 torture_comment(tctx, "attempt BRL test\n");
3394 status = smbcli_lock(cli1->tree, fnum, 0, 4, 0, WRITE_LOCK);
3395 CHECK_STATUS(tctx, status, NT_STATUS_OK);
3398 * Even though level 2 oplock breaks are asynchrounous, with self
3399 * contention we'll always break the oplock before the contending
3400 * operation's response is sent.
3402 CHECK_VAL(break_info.count, 1);
3403 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
3404 CHECK_VAL(break_info.fnum, fnum);
3405 CHECK_VAL(break_info.failures, 0);
3407 /* expect no oplock break */
3408 ZERO_STRUCT(break_info);
3409 status = smbcli_lock(cli1->tree, fnum, 2, 4, 0, WRITE_LOCK);
3410 CHECK_STATUS(tctx, status, NT_STATUS_LOCK_NOT_GRANTED);
3412 CHECK_VAL(break_info.count, 0);
3413 CHECK_VAL(break_info.level, 0);
3414 CHECK_VAL(break_info.fnum, 0);
3415 CHECK_VAL(break_info.failures, 0);
3417 smbcli_close(cli1->tree, fnum);
3418 smbcli_close(cli1->tree, fnum2);
3420 done:
3421 smb_raw_exit(cli1->session);
3422 smbcli_deltree(cli1->tree, BASEDIR);
3423 return ret;
3428 basic testing of oplocks
3430 struct torture_suite *torture_raw_oplock(TALLOC_CTX *mem_ctx)
3432 struct torture_suite *suite = torture_suite_create(mem_ctx, "OPLOCK");
3434 torture_suite_add_2smb_test(suite, "EXCLUSIVE1", test_raw_oplock_exclusive1);
3435 torture_suite_add_2smb_test(suite, "EXCLUSIVE2", test_raw_oplock_exclusive2);
3436 torture_suite_add_2smb_test(suite, "EXCLUSIVE3", test_raw_oplock_exclusive3);
3437 torture_suite_add_2smb_test(suite, "EXCLUSIVE4", test_raw_oplock_exclusive4);
3438 torture_suite_add_2smb_test(suite, "EXCLUSIVE5", test_raw_oplock_exclusive5);
3439 torture_suite_add_2smb_test(suite, "EXCLUSIVE6", test_raw_oplock_exclusive6);
3440 torture_suite_add_2smb_test(suite, "BATCH1", test_raw_oplock_batch1);
3441 torture_suite_add_2smb_test(suite, "BATCH2", test_raw_oplock_batch2);
3442 torture_suite_add_2smb_test(suite, "BATCH3", test_raw_oplock_batch3);
3443 torture_suite_add_2smb_test(suite, "BATCH4", test_raw_oplock_batch4);
3444 torture_suite_add_2smb_test(suite, "BATCH5", test_raw_oplock_batch5);
3445 torture_suite_add_2smb_test(suite, "BATCH6", test_raw_oplock_batch6);
3446 torture_suite_add_2smb_test(suite, "BATCH7", test_raw_oplock_batch7);
3447 torture_suite_add_2smb_test(suite, "BATCH8", test_raw_oplock_batch8);
3448 torture_suite_add_2smb_test(suite, "BATCH9", test_raw_oplock_batch9);
3449 torture_suite_add_2smb_test(suite, "BATCH10", test_raw_oplock_batch10);
3450 torture_suite_add_2smb_test(suite, "BATCH11", test_raw_oplock_batch11);
3451 torture_suite_add_2smb_test(suite, "BATCH12", test_raw_oplock_batch12);
3452 torture_suite_add_2smb_test(suite, "BATCH13", test_raw_oplock_batch13);
3453 torture_suite_add_2smb_test(suite, "BATCH14", test_raw_oplock_batch14);
3454 torture_suite_add_2smb_test(suite, "BATCH15", test_raw_oplock_batch15);
3455 torture_suite_add_2smb_test(suite, "BATCH16", test_raw_oplock_batch16);
3456 torture_suite_add_2smb_test(suite, "BATCH17", test_raw_oplock_batch17);
3457 torture_suite_add_2smb_test(suite, "BATCH18", test_raw_oplock_batch18);
3458 torture_suite_add_2smb_test(suite, "BATCH19", test_raw_oplock_batch19);
3459 torture_suite_add_2smb_test(suite, "BATCH20", test_raw_oplock_batch20);
3460 torture_suite_add_2smb_test(suite, "BATCH21", test_raw_oplock_batch21);
3461 torture_suite_add_2smb_test(suite, "BATCH22", test_raw_oplock_batch22);
3462 torture_suite_add_2smb_test(suite, "BATCH23", test_raw_oplock_batch23);
3463 torture_suite_add_2smb_test(suite, "BATCH24", test_raw_oplock_batch24);
3464 torture_suite_add_2smb_test(suite, "BATCH25", test_raw_oplock_batch25);
3465 torture_suite_add_2smb_test(suite, "STREAM1", test_raw_oplock_stream1);
3466 torture_suite_add_1smb_test(suite, "DOC1", test_raw_oplock_doc);
3467 torture_suite_add_2smb_test(suite, "BRL1", test_raw_oplock_brl1);
3468 torture_suite_add_1smb_test(suite, "BRL2", test_raw_oplock_brl2);
3469 torture_suite_add_1smb_test(suite, "BRL3", test_raw_oplock_brl3);
3471 return suite;
3475 stress testing of oplocks
3477 bool torture_bench_oplock(struct torture_context *torture)
3479 struct smbcli_state **cli;
3480 bool ret = true;
3481 TALLOC_CTX *mem_ctx = talloc_new(torture);
3482 int torture_nprocs = torture_setting_int(torture, "nprocs", 4);
3483 int i, count=0;
3484 int timelimit = torture_setting_int(torture, "timelimit", 10);
3485 union smb_open io;
3486 struct timeval tv;
3488 cli = talloc_array(mem_ctx, struct smbcli_state *, torture_nprocs);
3490 torture_comment(torture, "Opening %d connections\n", torture_nprocs);
3491 for (i=0;i<torture_nprocs;i++) {
3492 if (!torture_open_connection_ev(&cli[i], i, torture, torture->ev)) {
3493 return false;
3495 talloc_steal(mem_ctx, cli[i]);
3496 smbcli_oplock_handler(cli[i]->transport, oplock_handler_close,
3497 cli[i]->tree);
3500 if (!torture_setup_dir(cli[0], BASEDIR)) {
3501 ret = false;
3502 goto done;
3505 io.ntcreatex.level = RAW_OPEN_NTCREATEX;
3506 io.ntcreatex.in.root_fid = 0;
3507 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3508 io.ntcreatex.in.alloc_size = 0;
3509 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3510 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
3511 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3512 io.ntcreatex.in.create_options = 0;
3513 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3514 io.ntcreatex.in.security_flags = 0;
3515 io.ntcreatex.in.fname = BASEDIR "\\test.dat";
3516 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3517 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3518 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3520 tv = timeval_current();
3523 we open the same file with SHARE_ACCESS_NONE from all the
3524 connections in a round robin fashion. Each open causes an
3525 oplock break on the previous connection, which is answered
3526 by the oplock_handler_close() to close the file.
3528 This measures how fast we can pass on oplocks, and stresses
3529 the oplock handling code
3531 torture_comment(torture, "Running for %d seconds\n", timelimit);
3532 while (timeval_elapsed(&tv) < timelimit) {
3533 for (i=0;i<torture_nprocs;i++) {
3534 NTSTATUS status;
3536 status = smb_raw_open(cli[i]->tree, mem_ctx, &io);
3537 CHECK_STATUS(torture, status, NT_STATUS_OK);
3538 count++;
3541 if (torture_setting_bool(torture, "progress", true)) {
3542 torture_comment(torture, "%.2f ops/second\r", count/timeval_elapsed(&tv));
3546 torture_comment(torture, "%.2f ops/second\n", count/timeval_elapsed(&tv));
3548 smb_raw_exit(cli[torture_nprocs-1]->session);
3550 done:
3551 smb_raw_exit(cli[0]->session);
3552 smbcli_deltree(cli[0]->tree, BASEDIR);
3553 talloc_free(mem_ctx);
3554 return ret;
3558 static struct hold_oplock_info {
3559 const char *fname;
3560 bool close_on_break;
3561 uint32_t share_access;
3562 uint16_t fnum;
3563 } hold_info[] = {
3564 { BASEDIR "\\notshared_close", true,
3565 NTCREATEX_SHARE_ACCESS_NONE, },
3566 { BASEDIR "\\notshared_noclose", false,
3567 NTCREATEX_SHARE_ACCESS_NONE, },
3568 { BASEDIR "\\shared_close", true,
3569 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
3570 { BASEDIR "\\shared_noclose", false,
3571 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
3574 static bool oplock_handler_hold(struct smbcli_transport *transport,
3575 uint16_t tid, uint16_t fnum, uint8_t level,
3576 void *private_data)
3578 struct smbcli_tree *tree = (struct smbcli_tree *)private_data;
3579 struct hold_oplock_info *info;
3580 int i;
3582 for (i=0;i<ARRAY_SIZE(hold_info);i++) {
3583 if (hold_info[i].fnum == fnum) break;
3586 if (i == ARRAY_SIZE(hold_info)) {
3587 printf("oplock break for unknown fnum %u\n", fnum);
3588 return false;
3591 info = &hold_info[i];
3593 if (info->close_on_break) {
3594 printf("oplock break on %s - closing\n",
3595 info->fname);
3596 oplock_handler_close(transport, tid, fnum, level, private_data);
3597 return true;
3600 printf("oplock break on %s - acking break\n", info->fname);
3602 return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
3607 used for manual testing of oplocks - especially interaction with
3608 other filesystems (such as NFS and local access)
3610 bool torture_hold_oplock(struct torture_context *torture,
3611 struct smbcli_state *cli)
3613 struct tevent_context *ev =
3614 (struct tevent_context *)cli->transport->socket->event.ctx;
3615 int i;
3617 printf("Setting up open files with oplocks in %s\n", BASEDIR);
3619 if (!torture_setup_dir(cli, BASEDIR)) {
3620 return false;
3623 smbcli_oplock_handler(cli->transport, oplock_handler_hold, cli->tree);
3625 /* setup the files */
3626 for (i=0;i<ARRAY_SIZE(hold_info);i++) {
3627 union smb_open io;
3628 NTSTATUS status;
3629 char c = 1;
3631 io.generic.level = RAW_OPEN_NTCREATEX;
3632 io.ntcreatex.in.root_fid = 0;
3633 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3634 io.ntcreatex.in.alloc_size = 0;
3635 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3636 io.ntcreatex.in.share_access = hold_info[i].share_access;
3637 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3638 io.ntcreatex.in.create_options = 0;
3639 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3640 io.ntcreatex.in.security_flags = 0;
3641 io.ntcreatex.in.fname = hold_info[i].fname;
3642 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
3643 NTCREATEX_FLAGS_REQUEST_OPLOCK |
3644 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3645 printf("opening %s\n", hold_info[i].fname);
3647 status = smb_raw_open(cli->tree, cli, &io);
3648 if (!NT_STATUS_IS_OK(status)) {
3649 printf("Failed to open %s - %s\n",
3650 hold_info[i].fname, nt_errstr(status));
3651 return false;
3654 if (io.ntcreatex.out.oplock_level != BATCH_OPLOCK_RETURN) {
3655 printf("Oplock not granted for %s - expected %d but got %d\n",
3656 hold_info[i].fname, BATCH_OPLOCK_RETURN,
3657 io.ntcreatex.out.oplock_level);
3658 return false;
3660 hold_info[i].fnum = io.ntcreatex.out.file.fnum;
3662 /* make the file non-zero size */
3663 if (smbcli_write(cli->tree, hold_info[i].fnum, 0, &c, 0, 1) != 1) {
3664 printf("Failed to write to file\n");
3665 return false;
3669 printf("Waiting for oplock events\n");
3670 event_loop_wait(ev);
3672 return true;