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