Add the oplock-batch25 test showing that a writeattr does not break an oplock
[samba.git] / source4 / torture / raw / oplock.c
1 /* 
2    Unix SMB/CIFS implementation.
3    basic raw test suite for oplocks
4    Copyright (C) Andrew Tridgell 2003
5    
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.
10    
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.
15    
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/>.
18 */
19
20 #include "includes.h"
21 #include "torture/torture.h"
22 #include "librpc/gen_ndr/security.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "libcli/raw/raw_proto.h"
25 #include "libcli/libcli.h"
26 #include "torture/util.h"
27 #include "lib/events/events.h"
28 #include "param/param.h"
29 #include "lib/cmdline/popt_common.h"
30 #include "libcli/resolve/resolve.h"
31
32 #define CHECK_VAL(v, correct) do { \
33         if ((v) != (correct)) { \
34                 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
35                                 __location__, #v, (int)v, (int)correct); \
36                 ret = false; \
37         }} while (0)
38
39 #define CHECK_RANGE(v, min, max) do { \
40         if ((v) < (min) || (v) > (max)) { \
41                 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got %d - should be between %d and %d\n", \
42                                 __location__, #v, (int)v, (int)min, (int)max); \
43                 ret = false; \
44         }} while (0)
45
46 #define CHECK_STRMATCH(v, correct) do { \
47         if (!v || strstr((v),(correct)) == NULL) { \
48                 torture_result(tctx, TORTURE_FAIL,  "(%s): wrong value for %s got '%s' - should be '%s'\n", \
49                                 __location__, #v, v?v:"NULL", correct); \
50                 ret = false; \
51         } \
52 } while (0)
53
54 #define CHECK_STATUS(tctx, status, correct) do { \
55         if (!NT_STATUS_EQUAL(status, correct)) { \
56                 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
57                        nt_errstr(status), nt_errstr(correct)); \
58                 ret = false; \
59                 goto done; \
60         }} while (0)
61
62
63 static struct {
64         int fnum;
65         uint8_t level;
66         int count;
67         int failures;
68 } break_info;
69
70 #define BASEDIR "\\test_oplock"
71
72 /*
73   a handler function for oplock break requests. Ack it as a break to level II if possible
74 */
75 static bool oplock_handler_ack_to_given(struct smbcli_transport *transport,
76                                         uint16_t tid, uint16_t fnum,
77                                         uint8_t level, void *private)
78 {
79         struct smbcli_tree *tree = (struct smbcli_tree *)private;
80         const char *name;
81
82         break_info.fnum = fnum;
83         break_info.level = level;
84         break_info.count++;
85
86         switch (level) {
87         case OPLOCK_BREAK_TO_LEVEL_II:
88                 name = "level II";
89                 break;
90         case OPLOCK_BREAK_TO_NONE:
91                 name = "none";
92                 break;
93         default:
94                 name = "unknown";
95                 break_info.failures++;
96         }
97         printf("Acking to %s [0x%02X] in oplock handler\n",
98                 name, level);
99
100         return smbcli_oplock_ack(tree, fnum, level);
101 }
102
103 /*
104   a handler function for oplock break requests. Ack it as a break to none
105 */
106 static bool oplock_handler_ack_to_none(struct smbcli_transport *transport, 
107                                        uint16_t tid, uint16_t fnum, 
108                                        uint8_t level, void *private)
109 {
110         struct smbcli_tree *tree = (struct smbcli_tree *)private;
111         break_info.fnum = fnum;
112         break_info.level = level;
113         break_info.count++;
114
115         printf("Acking to none in oplock handler\n");
116
117         return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
118 }
119
120 /*
121   a handler function for oplock break requests. Let it timeout
122 */
123 static bool oplock_handler_timeout(struct smbcli_transport *transport,
124                                    uint16_t tid, uint16_t fnum,
125                                    uint8_t level, void *private)
126 {
127         break_info.fnum = fnum;
128         break_info.level = level;
129         break_info.count++;
130
131         printf("Let oplock break timeout\n");
132         return true;
133 }
134
135 static void oplock_handler_close_recv(struct smbcli_request *req)
136 {
137         NTSTATUS status;
138         status = smbcli_request_simple_recv(req);
139         if (!NT_STATUS_IS_OK(status)) {
140                 printf("close failed in oplock_handler_close\n");
141                 break_info.failures++;
142         }
143 }
144
145 /*
146   a handler function for oplock break requests - close the file
147 */
148 static bool oplock_handler_close(struct smbcli_transport *transport, uint16_t tid, 
149                                  uint16_t fnum, uint8_t level, void *private)
150 {
151         union smb_close io;
152         struct smbcli_tree *tree = (struct smbcli_tree *)private;
153         struct smbcli_request *req;
154
155         break_info.fnum = fnum;
156         break_info.level = level;
157         break_info.count++;
158
159         io.close.level = RAW_CLOSE_CLOSE;
160         io.close.in.file.fnum = fnum;
161         io.close.in.write_time = 0;
162         req = smb_raw_close_send(tree, &io);
163         if (req == NULL) {
164                 printf("failed to send close in oplock_handler_close\n");
165                 return false;
166         }
167
168         req->async.fn = oplock_handler_close_recv;
169         req->async.private = NULL;
170
171         return true;
172 }
173
174 static bool open_connection_no_level2_oplocks(struct torture_context *tctx,
175                                               struct smbcli_state **c)
176 {
177         NTSTATUS status;
178         struct smbcli_options options;
179         struct smbcli_session_options session_options;
180
181         lp_smbcli_options(tctx->lp_ctx, &options);
182         lp_smbcli_session_options(tctx->lp_ctx, &session_options);
183
184         options.use_level2_oplocks = false;
185
186         status = smbcli_full_connection(tctx, c,
187                                         torture_setting_string(tctx, "host", NULL),
188                                         lp_smb_ports(tctx->lp_ctx),
189                                         torture_setting_string(tctx, "share", NULL),
190                                         NULL, cmdline_credentials,
191                                         lp_resolve_context(tctx->lp_ctx),
192                                         tctx->ev, &options, &session_options);
193         if (!NT_STATUS_IS_OK(status)) {
194                 printf("Failed to open connection - %s\n", nt_errstr(status));
195                 return false;
196         }
197
198         return true;
199 }
200
201 static bool test_raw_oplock_exclusive1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
202 {
203         const char *fname = BASEDIR "\\test_exclusive1.dat";
204         NTSTATUS status;
205         bool ret = true;
206         union smb_open io;
207         union smb_unlink unl;
208         uint16_t fnum=0;
209
210         if (!torture_setup_dir(cli1, BASEDIR)) {
211                 return false;
212         }
213
214         /* cleanup */
215         smbcli_unlink(cli1->tree, fname);
216
217         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
218
219         /*
220           base ntcreatex parms
221         */
222         io.generic.level = RAW_OPEN_NTCREATEX;
223         io.ntcreatex.in.root_fid = 0;
224         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
225         io.ntcreatex.in.alloc_size = 0;
226         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
227         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
228         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
229         io.ntcreatex.in.create_options = 0;
230         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
231         io.ntcreatex.in.security_flags = 0;
232         io.ntcreatex.in.fname = fname;
233
234         torture_comment(tctx, "EXCLUSIVE1: open a file with an exclusive oplock (share mode: none)\n");
235         ZERO_STRUCT(break_info);
236         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
237
238         status = smb_raw_open(cli1->tree, tctx, &io);
239         CHECK_STATUS(tctx, status, NT_STATUS_OK);
240         fnum = io.ntcreatex.out.file.fnum;
241         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
242
243         torture_comment(tctx, "a 2nd open should not cause a break\n");
244         status = smb_raw_open(cli2->tree, tctx, &io);
245         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
246         CHECK_VAL(break_info.count, 0);
247         CHECK_VAL(break_info.failures, 0);
248
249         torture_comment(tctx, "unlink it - should also be no break\n");
250         unl.unlink.in.pattern = fname;
251         unl.unlink.in.attrib = 0;
252         status = smb_raw_unlink(cli2->tree, &unl);
253         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
254         CHECK_VAL(break_info.count, 0);
255         CHECK_VAL(break_info.failures, 0);
256
257         smbcli_close(cli1->tree, fnum);
258
259 done:
260         smb_raw_exit(cli1->session);
261         smb_raw_exit(cli2->session);
262         smbcli_deltree(cli1->tree, BASEDIR);
263         return ret;
264 }
265
266 static bool test_raw_oplock_exclusive2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
267 {
268         const char *fname = BASEDIR "\\test_exclusive2.dat";
269         NTSTATUS status;
270         bool ret = true;
271         union smb_open io;
272         union smb_unlink unl;
273         uint16_t fnum=0, fnum2=0;
274
275         if (!torture_setup_dir(cli1, BASEDIR)) {
276                 return false;
277         }
278
279         /* cleanup */
280         smbcli_unlink(cli1->tree, fname);
281
282         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
283
284         /*
285           base ntcreatex parms
286         */
287         io.generic.level = RAW_OPEN_NTCREATEX;
288         io.ntcreatex.in.root_fid = 0;
289         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
290         io.ntcreatex.in.alloc_size = 0;
291         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
292         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
293         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
294         io.ntcreatex.in.create_options = 0;
295         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
296         io.ntcreatex.in.security_flags = 0;
297         io.ntcreatex.in.fname = fname;
298
299         torture_comment(tctx, "EXCLUSIVE2: open a file with an exclusive oplock (share mode: all)\n");
300         ZERO_STRUCT(break_info);
301         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
302         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
303                 NTCREATEX_SHARE_ACCESS_WRITE|
304                 NTCREATEX_SHARE_ACCESS_DELETE;
305
306         status = smb_raw_open(cli1->tree, tctx, &io);
307         CHECK_STATUS(tctx, status, NT_STATUS_OK);
308         fnum = io.ntcreatex.out.file.fnum;
309         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
310
311         torture_comment(tctx, "a 2nd open should cause a break to level 2\n");
312         status = smb_raw_open(cli2->tree, tctx, &io);
313         CHECK_STATUS(tctx, status, NT_STATUS_OK);
314         fnum2 = io.ntcreatex.out.file.fnum;
315         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
316         CHECK_VAL(break_info.count, 1);
317         CHECK_VAL(break_info.fnum, fnum);
318         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
319         CHECK_VAL(break_info.failures, 0);
320         ZERO_STRUCT(break_info);
321
322         /* now we have 2 level II oplocks... */
323         torture_comment(tctx, "try to unlink it - should not cause a break, but a sharing violation\n");
324         unl.unlink.in.pattern = fname;
325         unl.unlink.in.attrib = 0;
326         status = smb_raw_unlink(cli2->tree, &unl);
327         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
328         CHECK_VAL(break_info.count, 0);
329         CHECK_VAL(break_info.failures, 0);
330
331         torture_comment(tctx, "close 1st handle\n");
332         smbcli_close(cli1->tree, fnum);
333
334         torture_comment(tctx, "try to unlink it - should not cause a break, but a sharing violation\n");
335         unl.unlink.in.pattern = fname;
336         unl.unlink.in.attrib = 0;
337         status = smb_raw_unlink(cli2->tree, &unl);
338         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
339         CHECK_VAL(break_info.count, 0);
340         CHECK_VAL(break_info.failures, 0);
341
342         torture_comment(tctx, "close 1st handle\n");
343         smbcli_close(cli2->tree, fnum2);
344
345         torture_comment(tctx, "unlink it\n");
346         unl.unlink.in.pattern = fname;
347         unl.unlink.in.attrib = 0;
348         status = smb_raw_unlink(cli2->tree, &unl);
349         CHECK_STATUS(tctx, status, NT_STATUS_OK);
350         CHECK_VAL(break_info.count, 0);
351         CHECK_VAL(break_info.failures, 0);
352
353 done:
354         smb_raw_exit(cli1->session);
355         smb_raw_exit(cli2->session);
356         smbcli_deltree(cli1->tree, BASEDIR);
357         return ret;
358 }
359
360 static bool test_raw_oplock_exclusive3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
361 {
362         const char *fname = BASEDIR "\\test_exclusive3.dat";
363         NTSTATUS status;
364         bool ret = true;
365         union smb_open io;
366         union smb_setfileinfo sfi;
367         uint16_t fnum=0;
368
369         if (!torture_setup_dir(cli1, BASEDIR)) {
370                 return false;
371         }
372
373         /* cleanup */
374         smbcli_unlink(cli1->tree, fname);
375
376         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
377
378         /*
379           base ntcreatex parms
380         */
381         io.generic.level = RAW_OPEN_NTCREATEX;
382         io.ntcreatex.in.root_fid = 0;
383         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
384         io.ntcreatex.in.alloc_size = 0;
385         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
386         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
387         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
388         io.ntcreatex.in.create_options = 0;
389         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
390         io.ntcreatex.in.security_flags = 0;
391         io.ntcreatex.in.fname = fname;
392
393         torture_comment(tctx, "EXCLUSIVE3: open a file with an exclusive oplock (share mode: none)\n");
394
395         ZERO_STRUCT(break_info);
396         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
397
398         status = smb_raw_open(cli1->tree, tctx, &io);
399         CHECK_STATUS(tctx, status, NT_STATUS_OK);
400         fnum = io.ntcreatex.out.file.fnum;
401         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
402
403         torture_comment(tctx, "setpathinfo EOF should trigger a break to none\n");
404         ZERO_STRUCT(sfi);
405         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
406         sfi.generic.in.file.path = fname;
407         sfi.end_of_file_info.in.size = 100;
408
409         status = smb_raw_setpathinfo(cli2->tree, &sfi);
410
411         CHECK_STATUS(tctx, status, NT_STATUS_OK);
412         CHECK_VAL(break_info.count, 1);
413         CHECK_VAL(break_info.failures, 0);
414         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
415
416         smbcli_close(cli1->tree, fnum);
417
418 done:
419         smb_raw_exit(cli1->session);
420         smb_raw_exit(cli2->session);
421         smbcli_deltree(cli1->tree, BASEDIR);
422         return ret;
423 }
424
425 static bool test_raw_oplock_exclusive4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
426 {
427         const char *fname = BASEDIR "\\test_exclusive4.dat";
428         NTSTATUS status;
429         bool ret = true;
430         union smb_open io;
431         uint16_t fnum=0, fnum2=0;
432
433         if (!torture_setup_dir(cli1, BASEDIR)) {
434                 return false;
435         }
436
437         /* cleanup */
438         smbcli_unlink(cli1->tree, fname);
439
440         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
441
442         /*
443           base ntcreatex parms
444         */
445         io.generic.level = RAW_OPEN_NTCREATEX;
446         io.ntcreatex.in.root_fid = 0;
447         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
448         io.ntcreatex.in.alloc_size = 0;
449         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
450         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
451         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
452         io.ntcreatex.in.create_options = 0;
453         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
454         io.ntcreatex.in.security_flags = 0;
455         io.ntcreatex.in.fname = fname;
456
457         torture_comment(tctx, "EXCLUSIVE4: open with exclusive oplock\n");
458         ZERO_STRUCT(break_info);
459         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
460
461         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
462         status = smb_raw_open(cli1->tree, tctx, &io);
463         CHECK_STATUS(tctx, status, NT_STATUS_OK);
464         fnum = io.ntcreatex.out.file.fnum;
465         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
466
467         ZERO_STRUCT(break_info);
468         torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
469
470         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
471         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
472         status = smb_raw_open(cli2->tree, tctx, &io);
473         CHECK_STATUS(tctx, status, NT_STATUS_OK);
474         fnum2 = io.ntcreatex.out.file.fnum;
475         CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
476         CHECK_VAL(break_info.count, 0);
477         CHECK_VAL(break_info.failures, 0);
478
479         smbcli_close(cli1->tree, fnum);
480         smbcli_close(cli2->tree, fnum2);
481
482 done:
483         smb_raw_exit(cli1->session);
484         smb_raw_exit(cli2->session);
485         smbcli_deltree(cli1->tree, BASEDIR);
486         return ret;
487 }
488
489 static bool test_raw_oplock_exclusive5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
490 {
491         const char *fname = BASEDIR "\\test_exclusive5.dat";
492         NTSTATUS status;
493         bool ret = true;
494         union smb_open io;
495         uint16_t fnum=0, fnum2=0;
496
497         if (!torture_setup_dir(cli1, BASEDIR)) {
498                 return false;
499         }
500
501         /* cleanup */
502         smbcli_unlink(cli1->tree, fname);
503
504         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
505         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
506
507         /*
508           base ntcreatex parms
509         */
510         io.generic.level = RAW_OPEN_NTCREATEX;
511         io.ntcreatex.in.root_fid = 0;
512         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
513         io.ntcreatex.in.alloc_size = 0;
514         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
515         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
516         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
517         io.ntcreatex.in.create_options = 0;
518         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
519         io.ntcreatex.in.security_flags = 0;
520         io.ntcreatex.in.fname = fname;
521
522         torture_comment(tctx, "EXCLUSIVE5: open with exclusive oplock\n");
523         ZERO_STRUCT(break_info);
524         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
525
526
527         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
528         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
529                 NTCREATEX_SHARE_ACCESS_WRITE|
530                 NTCREATEX_SHARE_ACCESS_DELETE;
531         status = smb_raw_open(cli1->tree, tctx, &io);
532         CHECK_STATUS(tctx, status, NT_STATUS_OK);
533         fnum = io.ntcreatex.out.file.fnum;
534         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
535
536         ZERO_STRUCT(break_info);
537
538         torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
539
540         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
541         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
542         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
543         status = smb_raw_open(cli2->tree, tctx, &io);
544         CHECK_STATUS(tctx, status, NT_STATUS_OK);
545         fnum2 = io.ntcreatex.out.file.fnum;
546         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
547         CHECK_VAL(break_info.count, 1);
548         CHECK_VAL(break_info.failures, 0);
549
550         smbcli_close(cli1->tree, fnum);
551         smbcli_close(cli2->tree, fnum2);
552
553 done:
554         smb_raw_exit(cli1->session);
555         smb_raw_exit(cli2->session);
556         smbcli_deltree(cli1->tree, BASEDIR);
557         return ret;
558 }
559
560 static bool test_raw_oplock_exclusive6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
561 {
562         const char *fname1 = BASEDIR "\\test_exclusive6_1.dat";
563         const char *fname2 = BASEDIR "\\test_exclusive6_2.dat";
564         NTSTATUS status;
565         bool ret = true;
566         union smb_open io;
567         union smb_rename rn;
568         uint16_t fnum=0;
569
570         if (!torture_setup_dir(cli1, BASEDIR)) {
571                 return false;
572         }
573
574         /* cleanup */
575         smbcli_unlink(cli1->tree, fname1);
576         smbcli_unlink(cli1->tree, fname2);
577
578         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
579
580         /*
581           base ntcreatex parms
582         */
583         io.generic.level = RAW_OPEN_NTCREATEX;
584         io.ntcreatex.in.root_fid = 0;
585         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
586         io.ntcreatex.in.alloc_size = 0;
587         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
588         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
589         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
590         io.ntcreatex.in.create_options = 0;
591         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
592         io.ntcreatex.in.security_flags = 0;
593         io.ntcreatex.in.fname = fname1;
594
595         torture_comment(tctx, "EXCLUSIVE6: open a file with an exclusive oplock (share mode: none)\n");
596         ZERO_STRUCT(break_info);
597         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
598
599         status = smb_raw_open(cli1->tree, tctx, &io);
600         CHECK_STATUS(tctx, status, NT_STATUS_OK);
601         fnum = io.ntcreatex.out.file.fnum;
602         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
603
604         torture_comment(tctx, "rename should not generate a break but get a sharing violation\n");
605         ZERO_STRUCT(rn);
606         rn.generic.level = RAW_RENAME_RENAME;
607         rn.rename.in.pattern1 = fname1;
608         rn.rename.in.pattern2 = fname2;
609         rn.rename.in.attrib = 0;
610
611         printf("trying rename while first file open\n");
612         status = smb_raw_rename(cli2->tree, &rn);
613
614         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
615         CHECK_VAL(break_info.count, 0);
616         CHECK_VAL(break_info.failures, 0);
617
618         smbcli_close(cli1->tree, fnum);
619
620 done:
621         smb_raw_exit(cli1->session);
622         smb_raw_exit(cli2->session);
623         smbcli_deltree(cli1->tree, BASEDIR);
624         return ret;
625 }
626
627 static bool test_raw_oplock_batch1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
628 {
629         const char *fname = BASEDIR "\\test_batch1.dat";
630         NTSTATUS status;
631         bool ret = true;
632         union smb_open io;
633         union smb_unlink unl;
634         uint16_t fnum=0;
635         char c = 0;
636
637         if (!torture_setup_dir(cli1, BASEDIR)) {
638                 return false;
639         }
640
641         /* cleanup */
642         smbcli_unlink(cli1->tree, fname);
643
644         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
645
646         /*
647           base ntcreatex parms
648         */
649         io.generic.level = RAW_OPEN_NTCREATEX;
650         io.ntcreatex.in.root_fid = 0;
651         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
652         io.ntcreatex.in.alloc_size = 0;
653         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
654         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
655         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
656         io.ntcreatex.in.create_options = 0;
657         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
658         io.ntcreatex.in.security_flags = 0;
659         io.ntcreatex.in.fname = fname;
660
661         /*
662           with a batch oplock we get a break
663         */
664         torture_comment(tctx, "BATCH1: open with batch oplock\n");
665         ZERO_STRUCT(break_info);
666         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
667                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
668                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
669         status = smb_raw_open(cli1->tree, tctx, &io);
670         CHECK_STATUS(tctx, status, NT_STATUS_OK);
671         fnum = io.ntcreatex.out.file.fnum;
672         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
673
674         torture_comment(tctx, "unlink should generate a break\n");
675         unl.unlink.in.pattern = fname;
676         unl.unlink.in.attrib = 0;
677         status = smb_raw_unlink(cli2->tree, &unl);
678         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
679
680         CHECK_VAL(break_info.count, 1);
681         CHECK_VAL(break_info.fnum, fnum);
682         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
683         CHECK_VAL(break_info.failures, 0);
684
685         torture_comment(tctx, "2nd unlink should not generate a break\n");
686         ZERO_STRUCT(break_info);
687         status = smb_raw_unlink(cli2->tree, &unl);
688         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
689
690         CHECK_VAL(break_info.count, 0);
691
692         torture_comment(tctx, "writing should generate a self break to none\n");
693         smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
694         msleep(100);
695         smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
696
697         CHECK_VAL(break_info.count, 1);
698         CHECK_VAL(break_info.fnum, fnum);
699         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
700         CHECK_VAL(break_info.failures, 0);
701
702         smbcli_close(cli1->tree, fnum);
703
704 done:
705         smb_raw_exit(cli1->session);
706         smb_raw_exit(cli2->session);
707         smbcli_deltree(cli1->tree, BASEDIR);
708         return ret;
709 }
710
711 static bool test_raw_oplock_batch2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
712 {
713         const char *fname = BASEDIR "\\test_batch2.dat";
714         NTSTATUS status;
715         bool ret = true;
716         union smb_open io;
717         union smb_unlink unl;
718         uint16_t fnum=0;
719         char c = 0;
720
721         if (!torture_setup_dir(cli1, BASEDIR)) {
722                 return false;
723         }
724
725         /* cleanup */
726         smbcli_unlink(cli1->tree, fname);
727
728         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
729
730         /*
731           base ntcreatex parms
732         */
733         io.generic.level = RAW_OPEN_NTCREATEX;
734         io.ntcreatex.in.root_fid = 0;
735         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
736         io.ntcreatex.in.alloc_size = 0;
737         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
738         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
739         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
740         io.ntcreatex.in.create_options = 0;
741         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
742         io.ntcreatex.in.security_flags = 0;
743         io.ntcreatex.in.fname = fname;
744
745         torture_comment(tctx, "BATCH2: open with batch oplock\n");
746         ZERO_STRUCT(break_info);
747         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
748                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
749                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
750         status = smb_raw_open(cli1->tree, tctx, &io);
751         CHECK_STATUS(tctx, status, NT_STATUS_OK);
752         fnum = io.ntcreatex.out.file.fnum;
753         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
754
755         torture_comment(tctx, "unlink should generate a break, which we ack as break to none\n");
756         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_none, cli1->tree);
757         unl.unlink.in.pattern = fname;
758         unl.unlink.in.attrib = 0;
759         status = smb_raw_unlink(cli2->tree, &unl);
760         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
761
762         CHECK_VAL(break_info.count, 1);
763         CHECK_VAL(break_info.fnum, fnum);
764         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
765         CHECK_VAL(break_info.failures, 0);
766
767         torture_comment(tctx, "2nd unlink should not generate a break\n");
768         ZERO_STRUCT(break_info);
769         status = smb_raw_unlink(cli2->tree, &unl);
770         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
771
772         CHECK_VAL(break_info.count, 0);
773
774         torture_comment(tctx, "writing should not generate a break\n");
775         smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
776         msleep(100);
777         smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
778
779         CHECK_VAL(break_info.count, 0);
780
781         smbcli_close(cli1->tree, fnum);
782
783 done:
784         smb_raw_exit(cli1->session);
785         smb_raw_exit(cli2->session);
786         smbcli_deltree(cli1->tree, BASEDIR);
787         return ret;
788 }
789
790 static bool test_raw_oplock_batch3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
791 {
792         const char *fname = BASEDIR "\\test_batch3.dat";
793         NTSTATUS status;
794         bool ret = true;
795         union smb_open io;
796         union smb_unlink unl;
797         uint16_t fnum=0;
798
799         if (!torture_setup_dir(cli1, BASEDIR)) {
800                 return false;
801         }
802
803         /* cleanup */
804         smbcli_unlink(cli1->tree, fname);
805
806         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
807
808         /*
809           base ntcreatex parms
810         */
811         io.generic.level = RAW_OPEN_NTCREATEX;
812         io.ntcreatex.in.root_fid = 0;
813         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
814         io.ntcreatex.in.alloc_size = 0;
815         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
816         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
817         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
818         io.ntcreatex.in.create_options = 0;
819         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
820         io.ntcreatex.in.security_flags = 0;
821         io.ntcreatex.in.fname = fname;
822
823         torture_comment(tctx, "BATCH3: if we close on break then the unlink can succeed\n");
824         ZERO_STRUCT(break_info);
825         smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
826         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
827                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
828                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
829         status = smb_raw_open(cli1->tree, tctx, &io);
830         CHECK_STATUS(tctx, status, NT_STATUS_OK);
831         fnum = io.ntcreatex.out.file.fnum;
832         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
833
834         unl.unlink.in.pattern = fname;
835         unl.unlink.in.attrib = 0;
836         ZERO_STRUCT(break_info);
837         status = smb_raw_unlink(cli2->tree, &unl);
838         CHECK_STATUS(tctx, status, NT_STATUS_OK);
839
840         CHECK_VAL(break_info.count, 1);
841         CHECK_VAL(break_info.fnum, fnum);
842         CHECK_VAL(break_info.level, 1);
843         CHECK_VAL(break_info.failures, 0);
844
845         smbcli_close(cli1->tree, fnum);
846
847 done:
848         smb_raw_exit(cli1->session);
849         smb_raw_exit(cli2->session);
850         smbcli_deltree(cli1->tree, BASEDIR);
851         return ret;
852 }
853
854 static bool test_raw_oplock_batch4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
855 {
856         const char *fname = BASEDIR "\\test_batch4.dat";
857         NTSTATUS status;
858         bool ret = true;
859         union smb_open io;
860         union smb_read rd;
861         uint16_t fnum=0;
862
863         if (!torture_setup_dir(cli1, BASEDIR)) {
864                 return false;
865         }
866
867         /* cleanup */
868         smbcli_unlink(cli1->tree, fname);
869
870         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
871
872         /*
873           base ntcreatex parms
874         */
875         io.generic.level = RAW_OPEN_NTCREATEX;
876         io.ntcreatex.in.root_fid = 0;
877         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
878         io.ntcreatex.in.alloc_size = 0;
879         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
880         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
881         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
882         io.ntcreatex.in.create_options = 0;
883         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
884         io.ntcreatex.in.security_flags = 0;
885         io.ntcreatex.in.fname = fname;
886
887         torture_comment(tctx, "BATCH4: a self read should not cause a break\n");
888         ZERO_STRUCT(break_info);
889         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
890
891         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
892                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
893                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
894         status = smb_raw_open(cli1->tree, tctx, &io);
895         CHECK_STATUS(tctx, status, NT_STATUS_OK);
896         fnum = io.ntcreatex.out.file.fnum;
897         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
898
899         rd.read.level = RAW_READ_READ;
900         rd.read.in.file.fnum = fnum;
901         rd.read.in.count = 1;
902         rd.read.in.offset = 0;
903         rd.read.in.remaining = 0;
904         status = smb_raw_read(cli1->tree, &rd);
905         CHECK_STATUS(tctx, status, NT_STATUS_OK);
906         CHECK_VAL(break_info.count, 0);
907         CHECK_VAL(break_info.failures, 0);
908
909         smbcli_close(cli1->tree, fnum);
910
911 done:
912         smb_raw_exit(cli1->session);
913         smb_raw_exit(cli2->session);
914         smbcli_deltree(cli1->tree, BASEDIR);
915         return ret;
916 }
917
918 static bool test_raw_oplock_batch5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
919 {
920         const char *fname = BASEDIR "\\test_batch5.dat";
921         NTSTATUS status;
922         bool ret = true;
923         union smb_open io;
924         uint16_t fnum=0;
925
926         if (!torture_setup_dir(cli1, BASEDIR)) {
927                 return false;
928         }
929
930         /* cleanup */
931         smbcli_unlink(cli1->tree, fname);
932
933         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
934
935         /*
936           base ntcreatex parms
937         */
938         io.generic.level = RAW_OPEN_NTCREATEX;
939         io.ntcreatex.in.root_fid = 0;
940         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
941         io.ntcreatex.in.alloc_size = 0;
942         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
943         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
944         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
945         io.ntcreatex.in.create_options = 0;
946         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
947         io.ntcreatex.in.security_flags = 0;
948         io.ntcreatex.in.fname = fname;
949
950         torture_comment(tctx, "BATCH5: a 2nd open should give a break\n");
951         ZERO_STRUCT(break_info);
952         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
953
954         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
955                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
956                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
957         status = smb_raw_open(cli1->tree, tctx, &io);
958         CHECK_STATUS(tctx, status, NT_STATUS_OK);
959         fnum = io.ntcreatex.out.file.fnum;
960         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
961
962         ZERO_STRUCT(break_info);
963
964         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
965         status = smb_raw_open(cli2->tree, tctx, &io);
966         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
967
968         CHECK_VAL(break_info.count, 1);
969         CHECK_VAL(break_info.fnum, fnum);
970         CHECK_VAL(break_info.level, 1);
971         CHECK_VAL(break_info.failures, 0);
972
973         smbcli_close(cli1->tree, fnum);
974
975 done:
976         smb_raw_exit(cli1->session);
977         smb_raw_exit(cli2->session);
978         smbcli_deltree(cli1->tree, BASEDIR);
979         return ret;
980 }
981
982 static bool test_raw_oplock_batch6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
983 {
984         const char *fname = BASEDIR "\\test_batch6.dat";
985         NTSTATUS status;
986         bool ret = true;
987         union smb_open io;
988         uint16_t fnum=0, fnum2=0;
989         char c = 0;
990
991         if (!torture_setup_dir(cli1, BASEDIR)) {
992                 return false;
993         }
994
995         /* cleanup */
996         smbcli_unlink(cli1->tree, fname);
997
998         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
999
1000         /*
1001           base ntcreatex parms
1002         */
1003         io.generic.level = RAW_OPEN_NTCREATEX;
1004         io.ntcreatex.in.root_fid = 0;
1005         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1006         io.ntcreatex.in.alloc_size = 0;
1007         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1008         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1009         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1010         io.ntcreatex.in.create_options = 0;
1011         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1012         io.ntcreatex.in.security_flags = 0;
1013         io.ntcreatex.in.fname = fname;
1014
1015         torture_comment(tctx, "BATCH6: a 2nd open should give a break to level II if the first open allowed shared read\n");
1016         ZERO_STRUCT(break_info);
1017         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1018         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1019
1020         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
1021         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
1022         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1023                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1024                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1025         status = smb_raw_open(cli1->tree, tctx, &io);
1026         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1027         fnum = io.ntcreatex.out.file.fnum;
1028         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1029
1030         ZERO_STRUCT(break_info);
1031
1032         status = smb_raw_open(cli2->tree, tctx, &io);
1033         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1034         fnum2 = io.ntcreatex.out.file.fnum;
1035         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1036
1037         CHECK_VAL(break_info.count, 1);
1038         CHECK_VAL(break_info.fnum, fnum);
1039         CHECK_VAL(break_info.level, 1);
1040         CHECK_VAL(break_info.failures, 0);
1041         ZERO_STRUCT(break_info);
1042
1043         torture_comment(tctx, "write should trigger a break to none on both\n");
1044         smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
1045         msleep(100);
1046         smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
1047
1048         CHECK_VAL(break_info.count, 2);
1049         CHECK_VAL(break_info.level, 0);
1050         CHECK_VAL(break_info.failures, 0);
1051
1052         smbcli_close(cli1->tree, fnum);
1053         smbcli_close(cli2->tree, fnum2);
1054
1055
1056 done:
1057         smb_raw_exit(cli1->session);
1058         smb_raw_exit(cli2->session);
1059         smbcli_deltree(cli1->tree, BASEDIR);
1060         return ret;
1061 }
1062
1063 static bool test_raw_oplock_batch7(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1064 {
1065         const char *fname = BASEDIR "\\test_batch7.dat";
1066         NTSTATUS status;
1067         bool ret = true;
1068         union smb_open io;
1069         uint16_t fnum=0, fnum2=0;
1070
1071         if (!torture_setup_dir(cli1, BASEDIR)) {
1072                 return false;
1073         }
1074
1075         /* cleanup */
1076         smbcli_unlink(cli1->tree, fname);
1077
1078         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1079
1080         /*
1081           base ntcreatex parms
1082         */
1083         io.generic.level = RAW_OPEN_NTCREATEX;
1084         io.ntcreatex.in.root_fid = 0;
1085         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1086         io.ntcreatex.in.alloc_size = 0;
1087         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1088         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1089         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1090         io.ntcreatex.in.create_options = 0;
1091         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1092         io.ntcreatex.in.security_flags = 0;
1093         io.ntcreatex.in.fname = fname;
1094
1095         torture_comment(tctx, "BATCH7: a 2nd open should get an oplock when we close instead of ack\n");
1096         ZERO_STRUCT(break_info);
1097         smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
1098
1099         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1100         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1101         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1102                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1103                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1104         status = smb_raw_open(cli1->tree, tctx, &io);
1105         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1106         fnum2 = io.ntcreatex.out.file.fnum;
1107         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1108
1109         ZERO_STRUCT(break_info);
1110
1111         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1112                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1113                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1114         status = smb_raw_open(cli2->tree, tctx, &io);
1115         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1116         fnum = io.ntcreatex.out.file.fnum;
1117         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1118
1119         CHECK_VAL(break_info.count, 1);
1120         CHECK_VAL(break_info.fnum, fnum2);
1121         CHECK_VAL(break_info.level, 1);
1122         CHECK_VAL(break_info.failures, 0);
1123         
1124         smbcli_close(cli2->tree, fnum);
1125
1126 done:
1127         smb_raw_exit(cli1->session);
1128         smb_raw_exit(cli2->session);
1129         smbcli_deltree(cli1->tree, BASEDIR);
1130         return ret;
1131 }
1132
1133 static bool test_raw_oplock_batch8(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1134 {
1135         const char *fname = BASEDIR "\\test_batch8.dat";
1136         NTSTATUS status;
1137         bool ret = true;
1138         union smb_open io;
1139         uint16_t fnum=0, fnum2=0;
1140
1141         if (!torture_setup_dir(cli1, BASEDIR)) {
1142                 return false;
1143         }
1144
1145         /* cleanup */
1146         smbcli_unlink(cli1->tree, fname);
1147
1148         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1149
1150         /*
1151           base ntcreatex parms
1152         */
1153         io.generic.level = RAW_OPEN_NTCREATEX;
1154         io.ntcreatex.in.root_fid = 0;
1155         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1156         io.ntcreatex.in.alloc_size = 0;
1157         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1158         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1159         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1160         io.ntcreatex.in.create_options = 0;
1161         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1162         io.ntcreatex.in.security_flags = 0;
1163         io.ntcreatex.in.fname = fname;
1164
1165         torture_comment(tctx, "BATCH8: open with batch oplock\n");
1166         ZERO_STRUCT(break_info);
1167         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1168
1169         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1170                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1171                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1172         status = smb_raw_open(cli1->tree, tctx, &io);
1173         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1174         fnum = io.ntcreatex.out.file.fnum;
1175         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1176
1177         ZERO_STRUCT(break_info);
1178         torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
1179
1180         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1181                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1182                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1183         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1184         status = smb_raw_open(cli2->tree, tctx, &io);
1185         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1186         fnum2 = io.ntcreatex.out.file.fnum;
1187         CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
1188         CHECK_VAL(break_info.count, 0);
1189         CHECK_VAL(break_info.failures, 0);
1190
1191         smbcli_close(cli1->tree, fnum);
1192         smbcli_close(cli2->tree, fnum2);
1193
1194 done:
1195         smb_raw_exit(cli1->session);
1196         smb_raw_exit(cli2->session);
1197         smbcli_deltree(cli1->tree, BASEDIR);
1198         return ret;
1199 }
1200
1201 static bool test_raw_oplock_batch9(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1202 {
1203         const char *fname = BASEDIR "\\test_batch9.dat";
1204         NTSTATUS status;
1205         bool ret = true;
1206         union smb_open io;
1207         uint16_t fnum=0, fnum2=0;
1208         char c = 0;
1209
1210         if (!torture_setup_dir(cli1, BASEDIR)) {
1211                 return false;
1212         }
1213
1214         /* cleanup */
1215         smbcli_unlink(cli1->tree, fname);
1216
1217         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1218
1219         /*
1220           base ntcreatex parms
1221         */
1222         io.generic.level = RAW_OPEN_NTCREATEX;
1223         io.ntcreatex.in.root_fid = 0;
1224         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1225         io.ntcreatex.in.alloc_size = 0;
1226         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1227         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1228         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1229         io.ntcreatex.in.create_options = 0;
1230         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1231         io.ntcreatex.in.security_flags = 0;
1232         io.ntcreatex.in.fname = fname;
1233
1234         torture_comment(tctx, "BATCH9: open with attributes only can create file\n");
1235
1236         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1237                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1238                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1239         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1240         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1241         status = smb_raw_open(cli1->tree, tctx, &io);
1242         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1243         fnum = io.ntcreatex.out.file.fnum;
1244         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1245
1246         torture_comment(tctx, "Subsequent normal open should break oplock on attribute only open to level II\n");
1247
1248         ZERO_STRUCT(break_info);
1249         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1250
1251         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1252                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1253                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1254         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1255         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1256         status = smb_raw_open(cli2->tree, tctx, &io);
1257         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1258         fnum2 = io.ntcreatex.out.file.fnum;
1259         CHECK_VAL(break_info.count, 1);
1260         CHECK_VAL(break_info.fnum, fnum);
1261         CHECK_VAL(break_info.failures, 0);
1262         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1263         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1264         smbcli_close(cli2->tree, fnum2);
1265
1266         torture_comment(tctx, "third oplocked open should grant level2 without break\n");
1267         ZERO_STRUCT(break_info);
1268         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1269         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1270         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1271                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1272                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1273         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1274         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1275         status = smb_raw_open(cli2->tree, tctx, &io);
1276         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1277         fnum2 = io.ntcreatex.out.file.fnum;
1278         CHECK_VAL(break_info.count, 0);
1279         CHECK_VAL(break_info.failures, 0);
1280         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1281
1282         ZERO_STRUCT(break_info);
1283
1284         torture_comment(tctx, "write should trigger a break to none on both\n");
1285         smbcli_write(cli2->tree, fnum2, 0, &c, 0, 1);
1286
1287         /* Now the oplock break request comes in. But right now we can't
1288          * answer it. Do another write */
1289
1290         msleep(100);
1291         smbcli_write(cli2->tree, fnum2, 0, &c, 1, 1);
1292
1293         CHECK_VAL(break_info.count, 2);
1294         CHECK_VAL(break_info.level, 0);
1295         CHECK_VAL(break_info.failures, 0);
1296
1297         smbcli_close(cli1->tree, fnum);
1298         smbcli_close(cli2->tree, fnum2);
1299
1300 done:
1301         smb_raw_exit(cli1->session);
1302         smb_raw_exit(cli2->session);
1303         smbcli_deltree(cli1->tree, BASEDIR);
1304         return ret;
1305 }
1306
1307 static bool test_raw_oplock_batch10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1308 {
1309         const char *fname = BASEDIR "\\test_batch10.dat";
1310         NTSTATUS status;
1311         bool ret = true;
1312         union smb_open io;
1313         uint16_t fnum=0, fnum2=0;
1314
1315         if (!torture_setup_dir(cli1, BASEDIR)) {
1316                 return false;
1317         }
1318
1319         /* cleanup */
1320         smbcli_unlink(cli1->tree, fname);
1321
1322         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1323
1324         /*
1325           base ntcreatex parms
1326         */
1327         io.generic.level = RAW_OPEN_NTCREATEX;
1328         io.ntcreatex.in.root_fid = 0;
1329         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1330         io.ntcreatex.in.alloc_size = 0;
1331         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1332         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1333         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1334         io.ntcreatex.in.create_options = 0;
1335         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1336         io.ntcreatex.in.security_flags = 0;
1337         io.ntcreatex.in.fname = fname;
1338
1339         torture_comment(tctx, "BATCH10: Open with oplock after a non-oplock open should grant level2\n");
1340         ZERO_STRUCT(break_info);
1341         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1342         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1343         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1344                 NTCREATEX_SHARE_ACCESS_WRITE|
1345                 NTCREATEX_SHARE_ACCESS_DELETE;
1346         status = smb_raw_open(cli1->tree, tctx, &io);
1347         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1348         fnum = io.ntcreatex.out.file.fnum;
1349         CHECK_VAL(break_info.count, 0);
1350         CHECK_VAL(break_info.failures, 0);
1351         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
1352
1353         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
1354
1355         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1356                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1357                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1358         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1359         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1360                 NTCREATEX_SHARE_ACCESS_WRITE|
1361                 NTCREATEX_SHARE_ACCESS_DELETE;
1362         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1363         status = smb_raw_open(cli2->tree, tctx, &io);
1364         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1365         fnum2 = io.ntcreatex.out.file.fnum;
1366         CHECK_VAL(break_info.count, 0);
1367         CHECK_VAL(break_info.failures, 0);
1368         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1369
1370         torture_comment(tctx, "write should trigger a break to none\n");
1371         {
1372                 union smb_write wr;
1373                 wr.write.level = RAW_WRITE_WRITE;
1374                 wr.write.in.file.fnum = fnum;
1375                 wr.write.in.count = 1;
1376                 wr.write.in.offset = 0;
1377                 wr.write.in.remaining = 0;
1378                 wr.write.in.data = (const uint8_t *)"x";
1379                 status = smb_raw_write(cli1->tree, &wr);
1380                 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1381         }
1382
1383         /* Now the oplock break request comes in. But right now we can't
1384          * answer it. Do another write */
1385
1386         msleep(100);
1387         
1388         {
1389                 union smb_write wr;
1390                 wr.write.level = RAW_WRITE_WRITE;
1391                 wr.write.in.file.fnum = fnum;
1392                 wr.write.in.count = 1;
1393                 wr.write.in.offset = 0;
1394                 wr.write.in.remaining = 0;
1395                 wr.write.in.data = (const uint8_t *)"x";
1396                 status = smb_raw_write(cli1->tree, &wr);
1397                 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1398         }
1399
1400         CHECK_VAL(break_info.count, 1);
1401         CHECK_VAL(break_info.fnum, fnum2);
1402         CHECK_VAL(break_info.level, 0);
1403         CHECK_VAL(break_info.failures, 0);
1404
1405         smbcli_close(cli1->tree, fnum);
1406         smbcli_close(cli2->tree, fnum2);
1407
1408 done:
1409         smb_raw_exit(cli1->session);
1410         smb_raw_exit(cli2->session);
1411         smbcli_deltree(cli1->tree, BASEDIR);
1412         return ret;
1413 }
1414
1415 static bool test_raw_oplock_batch11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1416 {
1417         const char *fname = BASEDIR "\\test_batch11.dat";
1418         NTSTATUS status;
1419         bool ret = true;
1420         union smb_open io;
1421         union smb_setfileinfo sfi;
1422         uint16_t fnum=0;
1423
1424         if (!torture_setup_dir(cli1, BASEDIR)) {
1425                 return false;
1426         }
1427
1428         /* cleanup */
1429         smbcli_unlink(cli1->tree, fname);
1430
1431         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1432
1433         /*
1434           base ntcreatex parms
1435         */
1436         io.generic.level = RAW_OPEN_NTCREATEX;
1437         io.ntcreatex.in.root_fid = 0;
1438         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1439         io.ntcreatex.in.alloc_size = 0;
1440         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1441         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1442         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1443         io.ntcreatex.in.create_options = 0;
1444         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1445         io.ntcreatex.in.security_flags = 0;
1446         io.ntcreatex.in.fname = fname;
1447
1448         /* Test if a set-eof on pathname breaks an exclusive oplock. */
1449         torture_comment(tctx, "BATCH11: Test if setpathinfo set EOF breaks oplocks.\n");
1450
1451         ZERO_STRUCT(break_info);
1452         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1453
1454         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1455                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1456                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1457         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1458         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1459                 NTCREATEX_SHARE_ACCESS_WRITE|
1460                 NTCREATEX_SHARE_ACCESS_DELETE;
1461         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1462         status = smb_raw_open(cli1->tree, tctx, &io);
1463         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1464         fnum = io.ntcreatex.out.file.fnum;
1465         CHECK_VAL(break_info.count, 0);
1466         CHECK_VAL(break_info.failures, 0);
1467         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1468         
1469         ZERO_STRUCT(sfi);
1470         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1471         sfi.generic.in.file.path = fname;
1472         sfi.end_of_file_info.in.size = 100;
1473
1474         status = smb_raw_setpathinfo(cli2->tree, &sfi);
1475
1476         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1477         CHECK_VAL(break_info.count, 1);
1478         CHECK_VAL(break_info.failures, 0);
1479         CHECK_VAL(break_info.level, 0);
1480
1481         smbcli_close(cli1->tree, fnum);
1482
1483 done:
1484         smb_raw_exit(cli1->session);
1485         smb_raw_exit(cli2->session);
1486         smbcli_deltree(cli1->tree, BASEDIR);
1487         return ret;
1488 }
1489
1490 static bool test_raw_oplock_batch12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1491 {
1492         const char *fname = BASEDIR "\\test_batch12.dat";
1493         NTSTATUS status;
1494         bool ret = true;
1495         union smb_open io;
1496         union smb_setfileinfo sfi;
1497         uint16_t fnum=0;
1498
1499         if (!torture_setup_dir(cli1, BASEDIR)) {
1500                 return false;
1501         }
1502
1503         /* cleanup */
1504         smbcli_unlink(cli1->tree, fname);
1505
1506         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1507
1508         /*
1509           base ntcreatex parms
1510         */
1511         io.generic.level = RAW_OPEN_NTCREATEX;
1512         io.ntcreatex.in.root_fid = 0;
1513         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1514         io.ntcreatex.in.alloc_size = 0;
1515         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1516         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1517         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1518         io.ntcreatex.in.create_options = 0;
1519         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1520         io.ntcreatex.in.security_flags = 0;
1521         io.ntcreatex.in.fname = fname;
1522
1523         /* Test if a set-allocation size on pathname breaks an exclusive oplock. */
1524         torture_comment(tctx, "BATCH12: Test if setpathinfo allocation size breaks oplocks.\n");
1525
1526         ZERO_STRUCT(break_info);
1527         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1528
1529         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1530                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1531                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1532         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1533         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1534                 NTCREATEX_SHARE_ACCESS_WRITE|
1535                 NTCREATEX_SHARE_ACCESS_DELETE;
1536         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1537         status = smb_raw_open(cli1->tree, tctx, &io);
1538         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1539         fnum = io.ntcreatex.out.file.fnum;
1540         CHECK_VAL(break_info.count, 0);
1541         CHECK_VAL(break_info.failures, 0);
1542         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1543         
1544         ZERO_STRUCT(sfi);
1545         sfi.generic.level = SMB_SFILEINFO_ALLOCATION_INFORMATION;
1546         sfi.generic.in.file.path = fname;
1547         sfi.allocation_info.in.alloc_size = 65536 * 8;
1548
1549         status = smb_raw_setpathinfo(cli2->tree, &sfi);
1550
1551         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1552         CHECK_VAL(break_info.count, 1);
1553         CHECK_VAL(break_info.failures, 0);
1554         CHECK_VAL(break_info.level, 0);
1555
1556         smbcli_close(cli1->tree, fnum);
1557
1558 done:
1559         smb_raw_exit(cli1->session);
1560         smb_raw_exit(cli2->session);
1561         smbcli_deltree(cli1->tree, BASEDIR);
1562         return ret;
1563 }
1564
1565 static bool test_raw_oplock_batch13(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1566 {
1567         const char *fname = BASEDIR "\\test_batch13.dat";
1568         NTSTATUS status;
1569         bool ret = true;
1570         union smb_open io;
1571         uint16_t fnum=0, fnum2=0;
1572
1573         if (!torture_setup_dir(cli1, BASEDIR)) {
1574                 return false;
1575         }
1576
1577         /* cleanup */
1578         smbcli_unlink(cli1->tree, fname);
1579
1580         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1581         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
1582
1583         /*
1584           base ntcreatex parms
1585         */
1586         io.generic.level = RAW_OPEN_NTCREATEX;
1587         io.ntcreatex.in.root_fid = 0;
1588         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1589         io.ntcreatex.in.alloc_size = 0;
1590         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1591         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1592         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1593         io.ntcreatex.in.create_options = 0;
1594         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1595         io.ntcreatex.in.security_flags = 0;
1596         io.ntcreatex.in.fname = fname;
1597
1598         torture_comment(tctx, "BATCH13: open with batch oplock\n");
1599         ZERO_STRUCT(break_info);
1600         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1601
1602
1603         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1604                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1605                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1606         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1607                 NTCREATEX_SHARE_ACCESS_WRITE|
1608                 NTCREATEX_SHARE_ACCESS_DELETE;
1609         status = smb_raw_open(cli1->tree, tctx, &io);
1610         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1611         fnum = io.ntcreatex.out.file.fnum;
1612         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1613
1614         ZERO_STRUCT(break_info);
1615
1616         torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE dispostion causes oplock break\n");
1617
1618         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1619                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1620                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1621         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1622         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1623                 NTCREATEX_SHARE_ACCESS_WRITE|
1624                 NTCREATEX_SHARE_ACCESS_DELETE;
1625         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
1626         status = smb_raw_open(cli2->tree, tctx, &io);
1627         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1628         fnum2 = io.ntcreatex.out.file.fnum;
1629         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1630         CHECK_VAL(break_info.count, 1);
1631         CHECK_VAL(break_info.failures, 0);
1632
1633         smbcli_close(cli1->tree, fnum);
1634         smbcli_close(cli2->tree, fnum2);
1635
1636 done:
1637         smb_raw_exit(cli1->session);
1638         smb_raw_exit(cli2->session);
1639         smbcli_deltree(cli1->tree, BASEDIR);
1640         return ret;
1641 }
1642
1643 static bool test_raw_oplock_batch14(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1644 {
1645         const char *fname = BASEDIR "\\test_batch14.dat";
1646         NTSTATUS status;
1647         bool ret = true;
1648         union smb_open io;
1649         uint16_t fnum=0, fnum2=0;
1650
1651         if (!torture_setup_dir(cli1, BASEDIR)) {
1652                 return false;
1653         }
1654
1655         /* cleanup */
1656         smbcli_unlink(cli1->tree, fname);
1657
1658         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1659
1660         /*
1661           base ntcreatex parms
1662         */
1663         io.generic.level = RAW_OPEN_NTCREATEX;
1664         io.ntcreatex.in.root_fid = 0;
1665         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1666         io.ntcreatex.in.alloc_size = 0;
1667         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1668         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1669         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1670         io.ntcreatex.in.create_options = 0;
1671         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1672         io.ntcreatex.in.security_flags = 0;
1673         io.ntcreatex.in.fname = fname;
1674
1675         torture_comment(tctx, "BATCH14: open with batch oplock\n");
1676         ZERO_STRUCT(break_info);
1677         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1678
1679         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1680                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1681                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1682         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1683                 NTCREATEX_SHARE_ACCESS_WRITE|
1684                 NTCREATEX_SHARE_ACCESS_DELETE;
1685         status = smb_raw_open(cli1->tree, tctx, &io);
1686         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1687         fnum = io.ntcreatex.out.file.fnum;
1688         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1689
1690         ZERO_STRUCT(break_info);
1691
1692         torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_SUPERSEDE dispostion causes oplock break\n");
1693
1694         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
1695                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
1696                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1697         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1698         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1699                 NTCREATEX_SHARE_ACCESS_WRITE|
1700                 NTCREATEX_SHARE_ACCESS_DELETE;
1701         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
1702         status = smb_raw_open(cli2->tree, tctx, &io);
1703         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1704         fnum2 = io.ntcreatex.out.file.fnum;
1705         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1706         CHECK_VAL(break_info.count, 1);
1707         CHECK_VAL(break_info.failures, 0);
1708
1709         smbcli_close(cli1->tree, fnum);
1710         smbcli_close(cli2->tree, fnum2);
1711 done:
1712         smb_raw_exit(cli1->session);
1713         smb_raw_exit(cli2->session);
1714         smbcli_deltree(cli1->tree, BASEDIR);
1715         return ret;
1716 }
1717
1718 static bool test_raw_oplock_batch15(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1719 {
1720         const char *fname = BASEDIR "\\test_batch15.dat";
1721         NTSTATUS status;
1722         bool ret = true;
1723         union smb_open io;
1724         union smb_fileinfo qfi;
1725         uint16_t fnum=0;
1726
1727         if (!torture_setup_dir(cli1, BASEDIR)) {
1728                 return false;
1729         }
1730
1731         /* cleanup */
1732         smbcli_unlink(cli1->tree, fname);
1733
1734         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1735
1736         /*
1737           base ntcreatex parms
1738         */
1739         io.generic.level = RAW_OPEN_NTCREATEX;
1740         io.ntcreatex.in.root_fid = 0;
1741         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1742         io.ntcreatex.in.alloc_size = 0;
1743         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1744         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1745         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1746         io.ntcreatex.in.create_options = 0;
1747         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1748         io.ntcreatex.in.security_flags = 0;
1749         io.ntcreatex.in.fname = fname;
1750
1751         /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
1752         torture_comment(tctx, "BATCH15: Test if qpathinfo all info breaks a batch oplock (should not).\n");
1753
1754         ZERO_STRUCT(break_info);
1755         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1756
1757         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1758                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1759                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1760         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1761         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1762                 NTCREATEX_SHARE_ACCESS_WRITE|
1763                 NTCREATEX_SHARE_ACCESS_DELETE;
1764         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1765         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1766         status = smb_raw_open(cli1->tree, tctx, &io);
1767         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1768         fnum = io.ntcreatex.out.file.fnum;
1769         CHECK_VAL(break_info.count, 0);
1770         CHECK_VAL(break_info.failures, 0);
1771         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1772
1773         ZERO_STRUCT(qfi);
1774         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1775         qfi.generic.in.file.path = fname;
1776
1777         status = smb_raw_pathinfo(cli2->tree, tctx, &qfi);
1778
1779         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1780         CHECK_VAL(break_info.count, 0);
1781
1782         smbcli_close(cli1->tree, fnum);
1783
1784 done:
1785         smb_raw_exit(cli1->session);
1786         smb_raw_exit(cli2->session);
1787         smbcli_deltree(cli1->tree, BASEDIR);
1788         return ret;
1789 }
1790
1791 static bool test_raw_oplock_batch16(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1792 {
1793         const char *fname = BASEDIR "\\test_batch16.dat";
1794         NTSTATUS status;
1795         bool ret = true;
1796         union smb_open io;
1797         uint16_t fnum=0, fnum2=0;
1798
1799         if (!torture_setup_dir(cli1, BASEDIR)) {
1800                 return false;
1801         }
1802
1803         /* cleanup */
1804         smbcli_unlink(cli1->tree, fname);
1805
1806         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1807         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
1808
1809         /*
1810           base ntcreatex parms
1811         */
1812         io.generic.level = RAW_OPEN_NTCREATEX;
1813         io.ntcreatex.in.root_fid = 0;
1814         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1815         io.ntcreatex.in.alloc_size = 0;
1816         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1817         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1818         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1819         io.ntcreatex.in.create_options = 0;
1820         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1821         io.ntcreatex.in.security_flags = 0;
1822         io.ntcreatex.in.fname = fname;
1823
1824         torture_comment(tctx, "BATCH16: open with batch oplock\n");
1825         ZERO_STRUCT(break_info);
1826         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1827
1828
1829         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1830                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1831                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1832         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1833                 NTCREATEX_SHARE_ACCESS_WRITE|
1834                 NTCREATEX_SHARE_ACCESS_DELETE;
1835         status = smb_raw_open(cli1->tree, tctx, &io);
1836         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1837         fnum = io.ntcreatex.out.file.fnum;
1838         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1839
1840         ZERO_STRUCT(break_info);
1841
1842         torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
1843
1844         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1845                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1846                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1847         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1848         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1849                 NTCREATEX_SHARE_ACCESS_WRITE|
1850                 NTCREATEX_SHARE_ACCESS_DELETE;
1851         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1852         status = smb_raw_open(cli2->tree, tctx, &io);
1853         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1854         fnum2 = io.ntcreatex.out.file.fnum;
1855         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1856         CHECK_VAL(break_info.count, 1);
1857         CHECK_VAL(break_info.failures, 0);
1858
1859         smbcli_close(cli1->tree, fnum);
1860         smbcli_close(cli2->tree, fnum2);
1861
1862 done:
1863         smb_raw_exit(cli1->session);
1864         smb_raw_exit(cli2->session);
1865         smbcli_deltree(cli1->tree, BASEDIR);
1866         return ret;
1867 }
1868
1869 static bool test_raw_oplock_batch17(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1870 {
1871         const char *fname1 = BASEDIR "\\test_batch17_1.dat";
1872         const char *fname2 = BASEDIR "\\test_batch17_2.dat";
1873         NTSTATUS status;
1874         bool ret = true;
1875         union smb_open io;
1876         union smb_rename rn;
1877         uint16_t fnum=0;
1878
1879         if (!torture_setup_dir(cli1, BASEDIR)) {
1880                 return false;
1881         }
1882
1883         /* cleanup */
1884         smbcli_unlink(cli1->tree, fname1);
1885         smbcli_unlink(cli1->tree, fname2);
1886
1887         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1888
1889         /*
1890           base ntcreatex parms
1891         */
1892         io.generic.level = RAW_OPEN_NTCREATEX;
1893         io.ntcreatex.in.root_fid = 0;
1894         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1895         io.ntcreatex.in.alloc_size = 0;
1896         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1897         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1898         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1899         io.ntcreatex.in.create_options = 0;
1900         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1901         io.ntcreatex.in.security_flags = 0;
1902         io.ntcreatex.in.fname = fname1;
1903
1904         torture_comment(tctx, "BATCH17: open a file with an batch oplock (share mode: none)\n");
1905
1906         ZERO_STRUCT(break_info);
1907         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1908                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1909                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1910
1911         status = smb_raw_open(cli1->tree, tctx, &io);
1912         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1913         fnum = io.ntcreatex.out.file.fnum;
1914         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1915
1916         torture_comment(tctx, "rename should trigger a break\n");
1917         ZERO_STRUCT(rn);
1918         rn.generic.level = RAW_RENAME_RENAME;
1919         rn.rename.in.pattern1 = fname1;
1920         rn.rename.in.pattern2 = fname2;
1921         rn.rename.in.attrib = 0;
1922
1923         printf("trying rename while first file open\n");
1924         status = smb_raw_rename(cli2->tree, &rn);
1925
1926         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1927         CHECK_VAL(break_info.count, 1);
1928         CHECK_VAL(break_info.failures, 0);
1929         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
1930
1931         smbcli_close(cli1->tree, fnum);
1932
1933 done:
1934         smb_raw_exit(cli1->session);
1935         smb_raw_exit(cli2->session);
1936         smbcli_deltree(cli1->tree, BASEDIR);
1937         return ret;
1938 }
1939
1940 static bool test_raw_oplock_batch18(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1941 {
1942         const char *fname1 = BASEDIR "\\test_batch18_1.dat";
1943         const char *fname2 = BASEDIR "\\test_batch18_2.dat";
1944         NTSTATUS status;
1945         bool ret = true;
1946         union smb_open io;
1947         union smb_rename rn;
1948         uint16_t fnum=0;
1949
1950         if (!torture_setup_dir(cli1, BASEDIR)) {
1951                 return false;
1952         }
1953
1954         /* cleanup */
1955         smbcli_unlink(cli1->tree, fname1);
1956         smbcli_unlink(cli1->tree, fname2);
1957
1958         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
1959
1960         /*
1961           base ntcreatex parms
1962         */
1963         io.generic.level = RAW_OPEN_NTCREATEX;
1964         io.ntcreatex.in.root_fid = 0;
1965         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1966         io.ntcreatex.in.alloc_size = 0;
1967         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1968         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1969         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1970         io.ntcreatex.in.create_options = 0;
1971         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1972         io.ntcreatex.in.security_flags = 0;
1973         io.ntcreatex.in.fname = fname1;
1974
1975         torture_comment(tctx, "BATCH18: open a file with an batch oplock (share mode: none)\n");
1976
1977         ZERO_STRUCT(break_info);
1978         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1979                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1980                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1981
1982         status = smb_raw_open(cli1->tree, tctx, &io);
1983         CHECK_STATUS(tctx, status, NT_STATUS_OK);
1984         fnum = io.ntcreatex.out.file.fnum;
1985         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1986
1987         torture_comment(tctx, "ntrename should trigger a break\n");
1988         ZERO_STRUCT(rn);
1989         rn.generic.level = RAW_RENAME_NTRENAME;
1990         rn.ntrename.in.attrib   = 0;
1991         rn.ntrename.in.flags    = RENAME_FLAG_RENAME;
1992         rn.ntrename.in.old_name = fname1;
1993         rn.ntrename.in.new_name = fname2;
1994         printf("trying rename while first file open\n");
1995         status = smb_raw_rename(cli2->tree, &rn);
1996
1997         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
1998         CHECK_VAL(break_info.count, 1);
1999         CHECK_VAL(break_info.failures, 0);
2000         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2001
2002         smbcli_close(cli1->tree, fnum);
2003
2004 done:
2005         smb_raw_exit(cli1->session);
2006         smb_raw_exit(cli2->session);
2007         smbcli_deltree(cli1->tree, BASEDIR);
2008         return ret;
2009 }
2010
2011 static bool test_raw_oplock_batch19(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2012 {
2013         const char *fname1 = BASEDIR "\\test_batch19_1.dat";
2014         const char *fname2 = BASEDIR "\\test_batch19_2.dat";
2015         const char *fname3 = BASEDIR "\\test_batch19_3.dat";
2016         NTSTATUS status;
2017         bool ret = true;
2018         union smb_open io;
2019         union smb_fileinfo qfi;
2020         union smb_setfileinfo sfi;
2021         uint16_t fnum=0;
2022
2023         if (!torture_setup_dir(cli1, BASEDIR)) {
2024                 return false;
2025         }
2026
2027         /* cleanup */
2028         smbcli_unlink(cli1->tree, fname1);
2029         smbcli_unlink(cli1->tree, fname2);
2030         smbcli_unlink(cli1->tree, fname3);
2031
2032         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2033
2034         /*
2035           base ntcreatex parms
2036         */
2037         io.generic.level = RAW_OPEN_NTCREATEX;
2038         io.ntcreatex.in.root_fid = 0;
2039         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2040         io.ntcreatex.in.alloc_size = 0;
2041         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2042         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2043         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2044         io.ntcreatex.in.create_options = 0;
2045         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2046         io.ntcreatex.in.security_flags = 0;
2047         io.ntcreatex.in.fname = fname1;
2048
2049         torture_comment(tctx, "BATCH19: open a file with an batch oplock (share mode: none)\n");
2050         ZERO_STRUCT(break_info);
2051         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2052                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2053                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2054         status = smb_raw_open(cli1->tree, tctx, &io);
2055         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2056         fnum = io.ntcreatex.out.file.fnum;
2057         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2058
2059         torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
2060         ZERO_STRUCT(sfi);
2061         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2062         sfi.generic.in.file.path = fname1;
2063         sfi.rename_information.in.overwrite     = 0;
2064         sfi.rename_information.in.root_fid      = 0;
2065         sfi.rename_information.in.new_name      = fname2+strlen(BASEDIR)+1;
2066
2067         status = smb_raw_setpathinfo(cli2->tree, &sfi);
2068
2069         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2070         CHECK_VAL(break_info.count, 0);
2071
2072         ZERO_STRUCT(qfi);
2073         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2074         qfi.generic.in.file.fnum = fnum;
2075
2076         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2077         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2078         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2079
2080         torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
2081         ZERO_STRUCT(sfi);
2082         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2083         sfi.generic.in.file.fnum = fnum;
2084         sfi.rename_information.in.overwrite     = 0;
2085         sfi.rename_information.in.root_fid      = 0;
2086         sfi.rename_information.in.new_name      = fname3+strlen(BASEDIR)+1;
2087
2088         status = smb_raw_setfileinfo(cli1->tree, &sfi);
2089         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2090         CHECK_VAL(break_info.count, 0);
2091
2092         ZERO_STRUCT(qfi);
2093         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2094         qfi.generic.in.file.fnum = fnum;
2095
2096         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2097         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2098         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2099
2100         smbcli_close(cli1->tree, fnum);
2101
2102 done:
2103         smb_raw_exit(cli1->session);
2104         smb_raw_exit(cli2->session);
2105         smbcli_deltree(cli1->tree, BASEDIR);
2106         return ret;
2107 }
2108
2109 /****************************************************
2110  Called from raw-rename - we need oplock handling for
2111  this test so this is why it's in oplock.c, not rename.c
2112 ****************************************************/
2113
2114 bool test_trans2rename(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2115 {
2116         const char *fname1 = BASEDIR "\\test_trans2rename_1.dat";
2117         const char *fname2 = BASEDIR "\\test_trans2rename_2.dat";
2118         const char *fname3 = BASEDIR "\\test_trans2rename_3.dat";
2119         NTSTATUS status;
2120         bool ret = true;
2121         union smb_open io;
2122         union smb_fileinfo qfi;
2123         union smb_setfileinfo sfi;
2124         uint16_t fnum=0;
2125
2126         if (!torture_setup_dir(cli1, BASEDIR)) {
2127                 return false;
2128         }
2129
2130         /* cleanup */
2131         smbcli_unlink(cli1->tree, fname1);
2132         smbcli_unlink(cli1->tree, fname2);
2133         smbcli_unlink(cli1->tree, fname3);
2134
2135         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2136
2137         /*
2138           base ntcreatex parms
2139         */
2140         io.generic.level = RAW_OPEN_NTCREATEX;
2141         io.ntcreatex.in.root_fid = 0;
2142         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2143         io.ntcreatex.in.alloc_size = 0;
2144         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2145         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2146         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2147         io.ntcreatex.in.create_options = 0;
2148         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2149         io.ntcreatex.in.security_flags = 0;
2150         io.ntcreatex.in.fname = fname1;
2151
2152         torture_comment(tctx, "open a file with an exclusive oplock (share mode: none)\n");
2153         ZERO_STRUCT(break_info);
2154         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2155                 NTCREATEX_FLAGS_REQUEST_OPLOCK;
2156         status = smb_raw_open(cli1->tree, tctx, &io);
2157         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2158         fnum = io.ntcreatex.out.file.fnum;
2159         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
2160
2161         torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
2162         ZERO_STRUCT(sfi);
2163         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2164         sfi.generic.in.file.path = fname1;
2165         sfi.rename_information.in.overwrite     = 0;
2166         sfi.rename_information.in.root_fid      = 0;
2167         sfi.rename_information.in.new_name      = fname2+strlen(BASEDIR)+1;
2168
2169         status = smb_raw_setpathinfo(cli2->tree, &sfi);
2170
2171         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2172         CHECK_VAL(break_info.count, 0);
2173
2174         ZERO_STRUCT(qfi);
2175         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2176         qfi.generic.in.file.fnum = fnum;
2177
2178         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2179         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2180         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2181
2182         torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
2183         ZERO_STRUCT(sfi);
2184         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2185         sfi.generic.in.file.fnum = fnum;
2186         sfi.rename_information.in.overwrite     = 0;
2187         sfi.rename_information.in.root_fid      = 0;
2188         sfi.rename_information.in.new_name      = fname3+strlen(BASEDIR)+1;
2189
2190         status = smb_raw_setfileinfo(cli1->tree, &sfi);
2191         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2192         CHECK_VAL(break_info.count, 0);
2193
2194         ZERO_STRUCT(qfi);
2195         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2196         qfi.generic.in.file.fnum = fnum;
2197
2198         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2199         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2200         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2201
2202         smbcli_close(cli1->tree, fnum);
2203
2204 done:
2205         smb_raw_exit(cli1->session);
2206         smb_raw_exit(cli2->session);
2207         smbcli_deltree(cli1->tree, BASEDIR);
2208         return ret;
2209 }
2210
2211 /****************************************************
2212  Called from raw-rename - we need oplock handling for
2213  this test so this is why it's in oplock.c, not rename.c
2214 ****************************************************/
2215
2216 bool test_nttransrename(struct torture_context *tctx, struct smbcli_state *cli1)
2217 {
2218         const char *fname1 = BASEDIR "\\test_nttransrename_1.dat";
2219         const char *fname2 = BASEDIR "\\test_nttransrename_2.dat";
2220         NTSTATUS status;
2221         bool ret = true;
2222         union smb_open io;
2223         union smb_fileinfo qfi, qpi;
2224         union smb_rename rn;
2225         uint16_t fnum=0;
2226
2227         if (!torture_setup_dir(cli1, BASEDIR)) {
2228                 return false;
2229         }
2230
2231         /* cleanup */
2232         smbcli_unlink(cli1->tree, fname1);
2233         smbcli_unlink(cli1->tree, fname2);
2234
2235         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2236
2237         /*
2238           base ntcreatex parms
2239         */
2240         io.generic.level = RAW_OPEN_NTCREATEX;
2241         io.ntcreatex.in.root_fid = 0;
2242         io.ntcreatex.in.access_mask = 0;/* ask for no access at all */;
2243         io.ntcreatex.in.alloc_size = 0;
2244         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2245         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2246         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2247         io.ntcreatex.in.create_options = 0;
2248         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2249         io.ntcreatex.in.security_flags = 0;
2250         io.ntcreatex.in.fname = fname1;
2251
2252         torture_comment(tctx, "nttrans_rename: open a file with an exclusive oplock (share mode: none)\n");
2253         ZERO_STRUCT(break_info);
2254         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2255                 NTCREATEX_FLAGS_REQUEST_OPLOCK;
2256         status = smb_raw_open(cli1->tree, tctx, &io);
2257         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2258         fnum = io.ntcreatex.out.file.fnum;
2259         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
2260
2261         torture_comment(tctx, "nttrans_rename: should not trigger a break nor a share mode violation\n");
2262         ZERO_STRUCT(rn);
2263         rn.generic.level = RAW_RENAME_NTTRANS;
2264         rn.nttrans.in.file.fnum = fnum;
2265         rn.nttrans.in.flags     = 0;
2266         rn.nttrans.in.new_name  = fname2+strlen(BASEDIR)+1;
2267
2268         status = smb_raw_rename(cli1->tree, &rn);
2269
2270         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2271         CHECK_VAL(break_info.count, 0);
2272
2273         /* w2k3 does nothing, it doesn't rename the file */
2274         torture_comment(tctx, "nttrans_rename: the server should have done nothing\n");
2275         ZERO_STRUCT(qfi);
2276         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2277         qfi.generic.in.file.fnum = fnum;
2278
2279         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2280         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2281         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname1);
2282
2283         ZERO_STRUCT(qpi);
2284         qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2285         qpi.generic.in.file.path = fname1;
2286
2287         status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2288         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2289         CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1);
2290
2291         ZERO_STRUCT(qpi);
2292         qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2293         qpi.generic.in.file.path = fname2;
2294
2295         status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2296         CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2297
2298         torture_comment(tctx, "nttrans_rename: after closing the file the file is still not renamed\n");
2299         status = smbcli_close(cli1->tree, fnum);
2300         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2301
2302         ZERO_STRUCT(qpi);
2303         qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2304         qpi.generic.in.file.path = fname1;
2305
2306         status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2307         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2308         CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1);
2309
2310         ZERO_STRUCT(qpi);
2311         qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2312         qpi.generic.in.file.path = fname2;
2313
2314         status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
2315         CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2316
2317         torture_comment(tctx, "nttrans_rename: rename with an invalid handle gives NT_STATUS_INVALID_HANDLE\n");
2318         ZERO_STRUCT(rn);
2319         rn.generic.level = RAW_RENAME_NTTRANS;
2320         rn.nttrans.in.file.fnum = fnum+1;
2321         rn.nttrans.in.flags     = 0;
2322         rn.nttrans.in.new_name  = fname2+strlen(BASEDIR)+1;
2323
2324         status = smb_raw_rename(cli1->tree, &rn);
2325
2326         CHECK_STATUS(tctx, status, NT_STATUS_INVALID_HANDLE);
2327
2328 done:
2329         smb_raw_exit(cli1->session);
2330         smbcli_deltree(cli1->tree, BASEDIR);
2331         return ret;
2332 }
2333
2334
2335 static bool test_raw_oplock_batch20(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2336 {
2337         const char *fname1 = BASEDIR "\\test_batch20_1.dat";
2338         const char *fname2 = BASEDIR "\\test_batch20_2.dat";
2339         const char *fname3 = BASEDIR "\\test_batch20_3.dat";
2340         NTSTATUS status;
2341         bool ret = true;
2342         union smb_open io;
2343         union smb_fileinfo qfi;
2344         union smb_setfileinfo sfi;
2345         uint16_t fnum=0,fnum2=0;
2346
2347         if (!torture_setup_dir(cli1, BASEDIR)) {
2348                 return false;
2349         }
2350
2351         /* cleanup */
2352         smbcli_unlink(cli1->tree, fname1);
2353         smbcli_unlink(cli1->tree, fname2);
2354         smbcli_unlink(cli1->tree, fname3);
2355
2356         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2357
2358         /*
2359           base ntcreatex parms
2360         */
2361         io.generic.level = RAW_OPEN_NTCREATEX;
2362         io.ntcreatex.in.root_fid = 0;
2363         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2364         io.ntcreatex.in.alloc_size = 0;
2365         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2366         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2367         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2368         io.ntcreatex.in.create_options = 0;
2369         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2370         io.ntcreatex.in.security_flags = 0;
2371         io.ntcreatex.in.fname = fname1;
2372
2373         torture_comment(tctx, "BATCH20: open a file with an batch oplock (share mode: all)\n");
2374         ZERO_STRUCT(break_info);
2375         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2376                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2377                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2378         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2379                 NTCREATEX_SHARE_ACCESS_WRITE|
2380                 NTCREATEX_SHARE_ACCESS_DELETE;
2381         status = smb_raw_open(cli1->tree, tctx, &io);
2382         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2383         fnum = io.ntcreatex.out.file.fnum;
2384         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2385
2386         torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
2387         ZERO_STRUCT(sfi);
2388         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2389         sfi.generic.in.file.path = fname1;
2390         sfi.rename_information.in.overwrite     = 0;
2391         sfi.rename_information.in.root_fid      = 0;
2392         sfi.rename_information.in.new_name      = fname2+strlen(BASEDIR)+1;
2393
2394         status = smb_raw_setpathinfo(cli2->tree, &sfi);
2395
2396         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2397         CHECK_VAL(break_info.count, 0);
2398
2399         ZERO_STRUCT(qfi);
2400         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2401         qfi.generic.in.file.fnum = fnum;
2402
2403         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2404         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2405         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
2406
2407         torture_comment(tctx, "open a file with the new name an batch oplock (share mode: all)\n");
2408         ZERO_STRUCT(break_info);
2409         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2410                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2411                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2412         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2413                 NTCREATEX_SHARE_ACCESS_WRITE|
2414                 NTCREATEX_SHARE_ACCESS_DELETE;
2415         io.ntcreatex.in.fname = fname2;
2416         status = smb_raw_open(cli2->tree, tctx, &io);
2417         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2418         fnum2 = io.ntcreatex.out.file.fnum;
2419         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2420         CHECK_VAL(break_info.count, 1);
2421         CHECK_VAL(break_info.failures, 0);
2422         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2423
2424         torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
2425         ZERO_STRUCT(sfi);
2426         sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2427         sfi.generic.in.file.fnum = fnum;
2428         sfi.rename_information.in.overwrite     = 0;
2429         sfi.rename_information.in.root_fid      = 0;
2430         sfi.rename_information.in.new_name      = fname3+strlen(BASEDIR)+1;
2431
2432         status = smb_raw_setfileinfo(cli1->tree, &sfi);
2433         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2434         CHECK_VAL(break_info.count, 1);
2435         CHECK_VAL(break_info.failures, 0);
2436         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2437
2438         ZERO_STRUCT(qfi);
2439         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2440         qfi.generic.in.file.fnum = fnum;
2441
2442         status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
2443         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2444         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2445
2446         ZERO_STRUCT(qfi);
2447         qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
2448         qfi.generic.in.file.fnum = fnum2;
2449
2450         status = smb_raw_fileinfo(cli2->tree, tctx, &qfi);
2451         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2452         CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
2453
2454         smbcli_close(cli1->tree, fnum);
2455
2456 done:
2457         smb_raw_exit(cli1->session);
2458         smb_raw_exit(cli2->session);
2459         smbcli_deltree(cli1->tree, BASEDIR);
2460         return ret;
2461 }
2462
2463 static bool test_raw_oplock_batch21(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2464 {
2465         const char *fname = BASEDIR "\\test_batch21.dat";
2466         NTSTATUS status;
2467         bool ret = true;
2468         union smb_open io;
2469         struct smb_echo e;
2470         uint16_t fnum=0;
2471         char c = 0;
2472         ssize_t wr;
2473
2474         if (!torture_setup_dir(cli1, BASEDIR)) {
2475                 return false;
2476         }
2477
2478         /* cleanup */
2479         smbcli_unlink(cli1->tree, fname);
2480
2481         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2482
2483         /*
2484           base ntcreatex parms
2485         */
2486         io.generic.level = RAW_OPEN_NTCREATEX;
2487         io.ntcreatex.in.root_fid = 0;
2488         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2489         io.ntcreatex.in.alloc_size = 0;
2490         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2491         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2492         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2493         io.ntcreatex.in.create_options = 0;
2494         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2495         io.ntcreatex.in.security_flags = 0;
2496         io.ntcreatex.in.fname = fname;
2497
2498         /*
2499           with a batch oplock we get a break
2500         */
2501         torture_comment(tctx, "BATCH21: open with batch oplock\n");
2502         ZERO_STRUCT(break_info);
2503         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2504                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2505                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2506         status = smb_raw_open(cli1->tree, tctx, &io);
2507         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2508         fnum = io.ntcreatex.out.file.fnum;
2509         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2510
2511         torture_comment(tctx, "writing should not generate a break\n");
2512         wr = smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
2513         CHECK_VAL(wr, 1);
2514         CHECK_STATUS(tctx, smbcli_nt_error(cli1->tree), NT_STATUS_OK);
2515
2516         ZERO_STRUCT(e);
2517         e.in.repeat_count = 1;
2518         status = smb_raw_echo(cli1->transport, &e);
2519         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2520
2521         CHECK_VAL(break_info.count, 0);
2522
2523         smbcli_close(cli1->tree, fnum);
2524
2525 done:
2526         smb_raw_exit(cli1->session);
2527         smb_raw_exit(cli2->session);
2528         smbcli_deltree(cli1->tree, BASEDIR);
2529         return ret;
2530 }
2531
2532 static bool test_raw_oplock_batch22(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2533 {
2534         const char *fname = BASEDIR "\\test_batch22.dat";
2535         NTSTATUS status;
2536         bool ret = true;
2537         union smb_open io;
2538         uint16_t fnum=0, fnum2=0;
2539         struct timeval tv;
2540         int timeout = torture_setting_int(tctx, "oplocktimeout", 30);
2541         int te;
2542
2543         if (torture_setting_bool(tctx, "samba3", false)) {
2544                 torture_skip(tctx, "BATCH22 disabled against samba3\n");
2545         }
2546
2547         if (!torture_setup_dir(cli1, BASEDIR)) {
2548                 return false;
2549         }
2550
2551         /* cleanup */
2552         smbcli_unlink(cli1->tree, fname);
2553
2554         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2555
2556         /*
2557           base ntcreatex parms
2558         */
2559         io.generic.level = RAW_OPEN_NTCREATEX;
2560         io.ntcreatex.in.root_fid = 0;
2561         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2562         io.ntcreatex.in.alloc_size = 0;
2563         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2564         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2565         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2566         io.ntcreatex.in.create_options = 0;
2567         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2568         io.ntcreatex.in.security_flags = 0;
2569         io.ntcreatex.in.fname = fname;
2570
2571         /*
2572           with a batch oplock we get a break
2573         */
2574         torture_comment(tctx, "BATCH22: open with batch oplock\n");
2575         ZERO_STRUCT(break_info);
2576         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2577                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2578                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2579         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
2580                 NTCREATEX_SHARE_ACCESS_WRITE|
2581                 NTCREATEX_SHARE_ACCESS_DELETE;
2582         status = smb_raw_open(cli1->tree, tctx, &io);
2583         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2584         fnum = io.ntcreatex.out.file.fnum;
2585         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2586
2587         torture_comment(tctx, "a 2nd open shoud not succeed after the oplock break timeout\n");
2588         tv = timeval_current();
2589         smbcli_oplock_handler(cli1->transport, oplock_handler_timeout, cli1->tree);
2590         status = smb_raw_open(cli1->tree, tctx, &io);
2591         CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
2592         te = (int)timeval_elapsed(&tv);
2593         CHECK_RANGE(te, timeout - 1, timeout + 15);
2594
2595         CHECK_VAL(break_info.count, 1);
2596         CHECK_VAL(break_info.fnum, fnum);
2597         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2598         CHECK_VAL(break_info.failures, 0);
2599         ZERO_STRUCT(break_info);
2600
2601         torture_comment(tctx, "a 2nd open shoud succeed after the oplock release without break\n");
2602         tv = timeval_current();
2603         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2604         status = smb_raw_open(cli1->tree, tctx, &io);
2605         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2606         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2607         te = (int)timeval_elapsed(&tv);
2608         /* it should come in without delay */
2609         CHECK_RANGE(te+1, 0, timeout);
2610         fnum2 = io.ntcreatex.out.file.fnum;
2611
2612         CHECK_VAL(break_info.count, 0);
2613
2614         smbcli_close(cli1->tree, fnum);
2615         smbcli_close(cli1->tree, fnum2);
2616
2617 done:
2618         smb_raw_exit(cli1->session);
2619         smb_raw_exit(cli2->session);
2620         smbcli_deltree(cli1->tree, BASEDIR);
2621         return ret;
2622 }
2623
2624 static bool test_raw_oplock_batch23(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2625 {
2626         const char *fname = BASEDIR "\\test_batch23.dat";
2627         NTSTATUS status;
2628         bool ret = true;
2629         union smb_open io;
2630         uint16_t fnum=0, fnum2=0,fnum3=0;
2631         struct smbcli_state *cli3 = NULL;
2632
2633         if (torture_setting_bool(tctx, "samba3", false)) {
2634                 torture_skip(tctx, "BATCH23 disabled against samba3\n");
2635         }
2636
2637         if (!torture_setup_dir(cli1, BASEDIR)) {
2638                 return false;
2639         }
2640
2641         /* cleanup */
2642         smbcli_unlink(cli1->tree, fname);
2643
2644         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2645
2646         ret = open_connection_no_level2_oplocks(tctx, &cli3);
2647         CHECK_VAL(ret, true);
2648
2649         /*
2650           base ntcreatex parms
2651         */
2652         io.generic.level = RAW_OPEN_NTCREATEX;
2653         io.ntcreatex.in.root_fid = 0;
2654         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2655         io.ntcreatex.in.alloc_size = 0;
2656         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2657         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2658         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2659         io.ntcreatex.in.create_options = 0;
2660         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2661         io.ntcreatex.in.security_flags = 0;
2662         io.ntcreatex.in.fname = fname;
2663
2664         torture_comment(tctx, "BATCH23: a open and ask for a batch oplock\n");
2665         ZERO_STRUCT(break_info);
2666         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2667         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
2668         smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
2669
2670         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
2671         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
2672         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2673                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2674                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2675         status = smb_raw_open(cli1->tree, tctx, &io);
2676         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2677         fnum = io.ntcreatex.out.file.fnum;
2678         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2679
2680         ZERO_STRUCT(break_info);
2681
2682         torture_comment(tctx, "a 2nd open without level2 oplock support should generate a break to level2\n");
2683         status = smb_raw_open(cli3->tree, tctx, &io);
2684         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2685         fnum3 = io.ntcreatex.out.file.fnum;
2686         CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
2687
2688         CHECK_VAL(break_info.count, 1);
2689         CHECK_VAL(break_info.fnum, fnum);
2690         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
2691         CHECK_VAL(break_info.failures, 0);
2692
2693         ZERO_STRUCT(break_info);
2694
2695         torture_comment(tctx, "a 3rd open with level2 oplock support should not generate a break\n");
2696         status = smb_raw_open(cli2->tree, tctx, &io);
2697         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2698         fnum2 = io.ntcreatex.out.file.fnum;
2699         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2700
2701         CHECK_VAL(break_info.count, 0);
2702
2703         smbcli_close(cli1->tree, fnum);
2704         smbcli_close(cli2->tree, fnum2);
2705         smbcli_close(cli3->tree, fnum3);
2706
2707 done:
2708         smb_raw_exit(cli1->session);
2709         smb_raw_exit(cli2->session);
2710         smb_raw_exit(cli3->session);
2711         smbcli_deltree(cli1->tree, BASEDIR);
2712         return ret;
2713 }
2714
2715 static bool test_raw_oplock_batch24(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2716 {
2717         const char *fname = BASEDIR "\\test_batch24.dat";
2718         NTSTATUS status;
2719         bool ret = true;
2720         union smb_open io;
2721         uint16_t fnum2=0,fnum3=0;
2722         struct smbcli_state *cli3 = NULL;
2723
2724         if (!torture_setup_dir(cli1, BASEDIR)) {
2725                 return false;
2726         }
2727
2728         /* cleanup */
2729         smbcli_unlink(cli1->tree, fname);
2730
2731         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2732
2733         ret = open_connection_no_level2_oplocks(tctx, &cli3);
2734         CHECK_VAL(ret, true);
2735
2736         /*
2737           base ntcreatex parms
2738         */
2739         io.generic.level = RAW_OPEN_NTCREATEX;
2740         io.ntcreatex.in.root_fid = 0;
2741         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2742         io.ntcreatex.in.alloc_size = 0;
2743         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2744         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2745         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2746         io.ntcreatex.in.create_options = 0;
2747         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2748         io.ntcreatex.in.security_flags = 0;
2749         io.ntcreatex.in.fname = fname;
2750
2751         torture_comment(tctx, "BATCH24: a open without level support and ask for a batch oplock\n");
2752         ZERO_STRUCT(break_info);
2753         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2754         smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
2755         smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
2756
2757         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
2758         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
2759         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2760                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2761                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2762         status = smb_raw_open(cli3->tree, tctx, &io);
2763         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2764         fnum3 = io.ntcreatex.out.file.fnum;
2765         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2766
2767         ZERO_STRUCT(break_info);
2768
2769         torture_comment(tctx, "a 2nd open with level2 oplock support should generate a break to none\n");
2770         status = smb_raw_open(cli2->tree, tctx, &io);
2771         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2772         fnum2 = io.ntcreatex.out.file.fnum;
2773         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
2774
2775         CHECK_VAL(break_info.count, 1);
2776         CHECK_VAL(break_info.fnum, fnum3);
2777         CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
2778         CHECK_VAL(break_info.failures, 0);
2779
2780         smbcli_close(cli3->tree, fnum3);
2781         smbcli_close(cli2->tree, fnum2);
2782
2783 done:
2784         smb_raw_exit(cli1->session);
2785         smb_raw_exit(cli2->session);
2786         smb_raw_exit(cli3->session);
2787         smbcli_deltree(cli1->tree, BASEDIR);
2788         return ret;
2789 }
2790
2791 static bool test_raw_oplock_batch25(struct torture_context *tctx,
2792                                     struct smbcli_state *cli1,
2793                                     struct smbcli_state *cli2)
2794 {
2795         const char *fname = BASEDIR "\\test_batch25.dat";
2796         NTSTATUS status;
2797         bool ret = true;
2798         union smb_open io;
2799         union smb_setfileinfo sfi;
2800         uint16_t fnum=0;
2801
2802         if (!torture_setup_dir(cli1, BASEDIR)) {
2803                 return false;
2804         }
2805
2806         /* cleanup */
2807         smbcli_unlink(cli1->tree, fname);
2808
2809         smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
2810
2811         /*
2812           base ntcreatex parms
2813         */
2814         io.generic.level = RAW_OPEN_NTCREATEX;
2815         io.ntcreatex.in.root_fid = 0;
2816         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2817         io.ntcreatex.in.alloc_size = 0;
2818         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2819         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2820         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2821         io.ntcreatex.in.create_options = 0;
2822         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2823         io.ntcreatex.in.security_flags = 0;
2824         io.ntcreatex.in.fname = fname;
2825
2826         torture_comment(tctx, "BATCH25: open a file with an batch oplock "
2827                         "(share mode: none)\n");
2828
2829         ZERO_STRUCT(break_info);
2830         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
2831                 NTCREATEX_FLAGS_REQUEST_OPLOCK |
2832                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2833         status = smb_raw_open(cli1->tree, tctx, &io);
2834         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2835         fnum = io.ntcreatex.out.file.fnum;
2836         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
2837
2838         torture_comment(tctx, "setpathinfo attribute info should not trigger "
2839                         "a break nor a violation\n");
2840         ZERO_STRUCT(sfi);
2841         sfi.generic.level = RAW_SFILEINFO_SETATTR;
2842         sfi.generic.in.file.path        = fname;
2843         sfi.setattr.in.attrib           = FILE_ATTRIBUTE_HIDDEN;
2844         sfi.setattr.in.write_time       = 0;
2845
2846         status = smb_raw_setpathinfo(cli2->tree, &sfi);
2847
2848         CHECK_STATUS(tctx, status, NT_STATUS_OK);
2849         CHECK_VAL(break_info.count, 0);
2850
2851         smbcli_close(cli1->tree, fnum);
2852
2853 done:
2854         smb_raw_exit(cli1->session);
2855         smb_raw_exit(cli2->session);
2856         smbcli_deltree(cli1->tree, BASEDIR);
2857         return ret;
2858 }
2859
2860 /* 
2861    basic testing of oplocks
2862 */
2863 struct torture_suite *torture_raw_oplock(TALLOC_CTX *mem_ctx)
2864 {
2865         struct torture_suite *suite = torture_suite_create(mem_ctx, "OPLOCK");
2866
2867         torture_suite_add_2smb_test(suite, "EXCLUSIVE1", test_raw_oplock_exclusive1);
2868         torture_suite_add_2smb_test(suite, "EXCLUSIVE2", test_raw_oplock_exclusive2);
2869         torture_suite_add_2smb_test(suite, "EXCLUSIVE3", test_raw_oplock_exclusive3);
2870         torture_suite_add_2smb_test(suite, "EXCLUSIVE4", test_raw_oplock_exclusive4);
2871         torture_suite_add_2smb_test(suite, "EXCLUSIVE5", test_raw_oplock_exclusive5);
2872         torture_suite_add_2smb_test(suite, "EXCLUSIVE6", test_raw_oplock_exclusive6);
2873         torture_suite_add_2smb_test(suite, "BATCH1", test_raw_oplock_batch1);
2874         torture_suite_add_2smb_test(suite, "BATCH2", test_raw_oplock_batch2);
2875         torture_suite_add_2smb_test(suite, "BATCH3", test_raw_oplock_batch3);
2876         torture_suite_add_2smb_test(suite, "BATCH4", test_raw_oplock_batch4);
2877         torture_suite_add_2smb_test(suite, "BATCH5", test_raw_oplock_batch5);
2878         torture_suite_add_2smb_test(suite, "BATCH6", test_raw_oplock_batch6);
2879         torture_suite_add_2smb_test(suite, "BATCH7", test_raw_oplock_batch7);
2880         torture_suite_add_2smb_test(suite, "BATCH8", test_raw_oplock_batch8);
2881         torture_suite_add_2smb_test(suite, "BATCH9", test_raw_oplock_batch9);
2882         torture_suite_add_2smb_test(suite, "BATCH10", test_raw_oplock_batch10);
2883         torture_suite_add_2smb_test(suite, "BATCH11", test_raw_oplock_batch11);
2884         torture_suite_add_2smb_test(suite, "BATCH12", test_raw_oplock_batch12);
2885         torture_suite_add_2smb_test(suite, "BATCH13", test_raw_oplock_batch13);
2886         torture_suite_add_2smb_test(suite, "BATCH14", test_raw_oplock_batch14);
2887         torture_suite_add_2smb_test(suite, "BATCH15", test_raw_oplock_batch15);
2888         torture_suite_add_2smb_test(suite, "BATCH16", test_raw_oplock_batch16);
2889         torture_suite_add_2smb_test(suite, "BATCH17", test_raw_oplock_batch17);
2890         torture_suite_add_2smb_test(suite, "BATCH18", test_raw_oplock_batch18);
2891         torture_suite_add_2smb_test(suite, "BATCH19", test_raw_oplock_batch19);
2892         torture_suite_add_2smb_test(suite, "BATCH20", test_raw_oplock_batch20);
2893         torture_suite_add_2smb_test(suite, "BATCH21", test_raw_oplock_batch21);
2894         torture_suite_add_2smb_test(suite, "BATCH22", test_raw_oplock_batch22);
2895         torture_suite_add_2smb_test(suite, "BATCH23", test_raw_oplock_batch23);
2896         torture_suite_add_2smb_test(suite, "BATCH24", test_raw_oplock_batch24);
2897         torture_suite_add_2smb_test(suite, "BATCH25", test_raw_oplock_batch25);
2898
2899         return suite;
2900 }
2901
2902 /* 
2903    stress testing of oplocks
2904 */
2905 bool torture_bench_oplock(struct torture_context *torture)
2906 {
2907         struct smbcli_state **cli;
2908         bool ret = true;
2909         TALLOC_CTX *mem_ctx = talloc_new(torture);
2910         int torture_nprocs = torture_setting_int(torture, "nprocs", 4);
2911         int i, count=0;
2912         int timelimit = torture_setting_int(torture, "timelimit", 10);
2913         union smb_open io;
2914         struct timeval tv;
2915
2916         cli = talloc_array(mem_ctx, struct smbcli_state *, torture_nprocs);
2917
2918         torture_comment(torture, "Opening %d connections\n", torture_nprocs);
2919         for (i=0;i<torture_nprocs;i++) {
2920                 if (!torture_open_connection_ev(&cli[i], i, torture, torture->ev)) {
2921                         return false;
2922                 }
2923                 talloc_steal(mem_ctx, cli[i]);
2924                 smbcli_oplock_handler(cli[i]->transport, oplock_handler_close, 
2925                                       cli[i]->tree);
2926         }
2927
2928         if (!torture_setup_dir(cli[0], BASEDIR)) {
2929                 ret = false;
2930                 goto done;
2931         }
2932
2933         io.ntcreatex.level = RAW_OPEN_NTCREATEX;
2934         io.ntcreatex.in.root_fid = 0;
2935         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2936         io.ntcreatex.in.alloc_size = 0;
2937         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2938         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2939         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
2940         io.ntcreatex.in.create_options = 0;
2941         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2942         io.ntcreatex.in.security_flags = 0;
2943         io.ntcreatex.in.fname = BASEDIR "\\test.dat";
2944         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
2945                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
2946                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
2947
2948         tv = timeval_current(); 
2949
2950         /*
2951           we open the same file with SHARE_ACCESS_NONE from all the
2952           connections in a round robin fashion. Each open causes an
2953           oplock break on the previous connection, which is answered
2954           by the oplock_handler_close() to close the file.
2955
2956           This measures how fast we can pass on oplocks, and stresses
2957           the oplock handling code
2958         */
2959         torture_comment(torture, "Running for %d seconds\n", timelimit);
2960         while (timeval_elapsed(&tv) < timelimit) {
2961                 for (i=0;i<torture_nprocs;i++) {
2962                         NTSTATUS status;
2963
2964                         status = smb_raw_open(cli[i]->tree, mem_ctx, &io);
2965                         CHECK_STATUS(torture, status, NT_STATUS_OK);
2966                         count++;
2967                 }
2968
2969                 if (torture_setting_bool(torture, "progress", true)) {
2970                         torture_comment(torture, "%.2f ops/second\r", count/timeval_elapsed(&tv));
2971                 }
2972         }
2973
2974         torture_comment(torture, "%.2f ops/second\n", count/timeval_elapsed(&tv));
2975
2976         smb_raw_exit(cli[torture_nprocs-1]->session);
2977         
2978 done:
2979         smb_raw_exit(cli[0]->session);
2980         smbcli_deltree(cli[0]->tree, BASEDIR);
2981         talloc_free(mem_ctx);
2982         return ret;
2983 }
2984
2985
2986 static struct hold_oplock_info {
2987         const char *fname;
2988         bool close_on_break;
2989         uint32_t share_access;
2990         uint16_t fnum;
2991 } hold_info[] = {
2992         { BASEDIR "\\notshared_close", true,  
2993           NTCREATEX_SHARE_ACCESS_NONE, },
2994         { BASEDIR "\\notshared_noclose", false, 
2995           NTCREATEX_SHARE_ACCESS_NONE, },
2996         { BASEDIR "\\shared_close", true,  
2997           NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
2998         { BASEDIR "\\shared_noclose", false,  
2999           NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
3000 };
3001
3002 static bool oplock_handler_hold(struct smbcli_transport *transport, 
3003                                 uint16_t tid, uint16_t fnum, uint8_t level, 
3004                                 void *private)
3005 {
3006         struct smbcli_tree *tree = (struct smbcli_tree *)private;
3007         struct hold_oplock_info *info;
3008         int i;
3009
3010         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
3011                 if (hold_info[i].fnum == fnum) break;
3012         }
3013
3014         if (i == ARRAY_SIZE(hold_info)) {
3015                 printf("oplock break for unknown fnum %u\n", fnum);
3016                 return false;
3017         }
3018
3019         info = &hold_info[i];
3020
3021         if (info->close_on_break) {
3022                 printf("oplock break on %s - closing\n",
3023                        info->fname);
3024                 oplock_handler_close(transport, tid, fnum, level, private);
3025                 return true;
3026         }
3027
3028         printf("oplock break on %s - acking break\n", info->fname);
3029
3030         return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
3031 }
3032
3033
3034 /* 
3035    used for manual testing of oplocks - especially interaction with
3036    other filesystems (such as NFS and local access)
3037 */
3038 bool torture_hold_oplock(struct torture_context *torture, 
3039                          struct smbcli_state *cli)
3040 {
3041         struct event_context *ev = 
3042                 (struct event_context *)cli->transport->socket->event.ctx;
3043         int i;
3044
3045         printf("Setting up open files with oplocks in %s\n", BASEDIR);
3046
3047         if (!torture_setup_dir(cli, BASEDIR)) {
3048                 return false;
3049         }
3050
3051         smbcli_oplock_handler(cli->transport, oplock_handler_hold, cli->tree);
3052
3053         /* setup the files */
3054         for (i=0;i<ARRAY_SIZE(hold_info);i++) {
3055                 union smb_open io;
3056                 NTSTATUS status;
3057                 char c = 1;
3058
3059                 io.generic.level = RAW_OPEN_NTCREATEX;
3060                 io.ntcreatex.in.root_fid = 0;
3061                 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
3062                 io.ntcreatex.in.alloc_size = 0;
3063                 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
3064                 io.ntcreatex.in.share_access = hold_info[i].share_access;
3065                 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
3066                 io.ntcreatex.in.create_options = 0;
3067                 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
3068                 io.ntcreatex.in.security_flags = 0;
3069                 io.ntcreatex.in.fname = hold_info[i].fname;
3070                 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
3071                         NTCREATEX_FLAGS_REQUEST_OPLOCK |
3072                         NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
3073                 printf("opening %s\n", hold_info[i].fname);
3074
3075                 status = smb_raw_open(cli->tree, cli, &io);
3076                 if (!NT_STATUS_IS_OK(status)) {
3077                         printf("Failed to open %s - %s\n", 
3078                                hold_info[i].fname, nt_errstr(status));
3079                         return false;
3080                 }
3081
3082                 if (io.ntcreatex.out.oplock_level != BATCH_OPLOCK_RETURN) {
3083                         printf("Oplock not granted for %s - expected %d but got %d\n", 
3084                                hold_info[i].fname, BATCH_OPLOCK_RETURN, 
3085                                 io.ntcreatex.out.oplock_level);
3086                         return false;
3087                 }
3088                 hold_info[i].fnum = io.ntcreatex.out.file.fnum;
3089
3090                 /* make the file non-zero size */
3091                 if (smbcli_write(cli->tree, hold_info[i].fnum, 0, &c, 0, 1) != 1) {
3092                         printf("Failed to write to file\n");
3093                         return false;
3094                 }
3095         }
3096
3097         printf("Waiting for oplock events\n");
3098         event_loop_wait(ev);
3099
3100         return true;
3101 }