fuzzing: fix fuzz_stable_sort_r_unstable comparison
[samba.git] / source4 / torture / raw / open.c
1 /* 
2    Unix SMB/CIFS implementation.
3    RAW_OPEN_* individual test suite
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 "libcli/raw/libcliraw.h"
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "lib/events/events.h"
25 #include "libcli/libcli.h"
26 #include "torture/util.h"
27 #include "torture/raw/proto.h"
28
29 /* enum for whether reads/writes are possible on a file */
30 enum rdwr_mode {RDWR_NONE, RDWR_RDONLY, RDWR_WRONLY, RDWR_RDWR};
31
32 #define BASEDIR "\\rawopen"
33
34 /*
35   check if a open file can be read/written
36 */
37 static enum rdwr_mode check_rdwr(struct smbcli_tree *tree, int fnum)
38 {
39         uint8_t c = 1;
40         bool can_read  = (smbcli_read(tree, fnum, &c, 0, 1) == 1);
41         bool can_write = (smbcli_write(tree, fnum, 0, &c, 0, 1) == 1);
42         if ( can_read &&  can_write) return RDWR_RDWR;
43         if ( can_read && !can_write) return RDWR_RDONLY;
44         if (!can_read &&  can_write) return RDWR_WRONLY;
45         return RDWR_NONE;
46 }
47
48 /*
49   describe a RDWR mode as a string
50 */
51 static const char *rdwr_string(enum rdwr_mode m)
52 {
53         switch (m) {
54         case RDWR_NONE: return "NONE";
55         case RDWR_RDONLY: return "RDONLY";
56         case RDWR_WRONLY: return "WRONLY";
57         case RDWR_RDWR: return "RDWR";
58         }
59         return "-";
60 }
61
62 #define CHECK_STATUS(status, correct) do { \
63         if (!NT_STATUS_EQUAL(status, correct)) { \
64                 torture_result(tctx, TORTURE_FAIL, \
65                         "(%s) Incorrect status %s - should be %s\n", \
66                        __location__, nt_errstr(status), nt_errstr(correct)); \
67                 ret = false; \
68                 goto done; \
69         }} while (0)
70
71 #define CREATE_FILE do { \
72         fnum = create_complex_file(cli, tctx, fname); \
73         if (fnum == -1) { \
74                 torture_result(tctx, TORTURE_FAIL, \
75                         "(%s) Failed to create %s - %s\n", \
76                          __location__, fname, smbcli_errstr(cli->tree)); \
77                 ret = false; \
78                 goto done; \
79         }} while (0)
80
81 #define CHECK_RDWR(fnum, correct) do { \
82         enum rdwr_mode m = check_rdwr(cli->tree, fnum); \
83         if (m != correct) { \
84                 torture_result(tctx, TORTURE_FAIL, \
85                        "(%s) Incorrect readwrite mode %s - expected %s\n", \
86                        __location__, rdwr_string(m), rdwr_string(correct)); \
87                 ret = false; \
88         }} while (0)
89
90 #define CHECK_TIME(t, field) do { \
91         time_t t1, t2; \
92         finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
93         finfo.all_info.in.file.path = fname; \
94         status = smb_raw_pathinfo(cli->tree, tctx, &finfo); \
95         CHECK_STATUS(status, NT_STATUS_OK); \
96         t1 = t & ~1; \
97         t2 = nt_time_to_unix(finfo.all_info.out.field) & ~1; \
98         if (labs(t1-t2) > 2) { \
99                 torture_result(tctx, TORTURE_FAIL, \
100                        "(%s) wrong time for field %s  %s - %s\n", \
101                        __location__, #field, \
102                        timestring(tctx, t1), \
103                        timestring(tctx, t2)); \
104                 dump_all_info(tctx, &finfo); \
105                 ret = false; \
106         }} while (0)
107
108 #define CHECK_NTTIME(t, field) do { \
109         NTTIME t2; \
110         finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
111         finfo.all_info.in.file.path = fname; \
112         status = smb_raw_pathinfo(cli->tree, tctx, &finfo); \
113         CHECK_STATUS(status, NT_STATUS_OK); \
114         t2 = finfo.all_info.out.field; \
115         if (llabs((int64_t)(t-t2)) > 20000) { \
116                 torture_result(tctx, TORTURE_FAIL, \
117                        "(%s) wrong time for field %s  %s - %s\n", \
118                        __location__, #field, \
119                        nt_time_string(tctx, t), \
120                        nt_time_string(tctx, t2)); \
121                 dump_all_info(tctx, &finfo); \
122                 ret = false; \
123         }} while (0)
124
125 #define CHECK_ALL_INFO(v, field) do { \
126         finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
127         finfo.all_info.in.file.path = fname; \
128         status = smb_raw_pathinfo(cli->tree, tctx, &finfo); \
129         CHECK_STATUS(status, NT_STATUS_OK); \
130         if ((v) != (finfo.all_info.out.field)) { \
131                 torture_result(tctx, TORTURE_FAIL, \
132                        "(%s) wrong value for field %s  0x%x - 0x%x\n", \
133                        __location__, #field, (unsigned int)(v), (unsigned int)(finfo.all_info.out.field)); \
134                 dump_all_info(tctx, &finfo); \
135                 ret = false; \
136         }} while (0)
137
138 #define CHECK_VAL(v, correct) do { \
139         if ((v) != (correct)) { \
140                 torture_result(tctx, TORTURE_FAIL, \
141                        "(%s) wrong value for %s  0x%x - should be 0x%x\n", \
142                        __location__, #v, (unsigned int)(v), (unsigned int)(correct)); \
143                 ret = false; \
144         }} while (0)
145
146 #define SET_ATTRIB(sattrib) do { \
147         union smb_setfileinfo sfinfo; \
148         ZERO_STRUCT(sfinfo.basic_info.in); \
149         sfinfo.basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION; \
150         sfinfo.basic_info.in.file.path = fname; \
151         sfinfo.basic_info.in.attrib = sattrib; \
152         status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
153         if (!NT_STATUS_IS_OK(status)) { \
154                 torture_warning(tctx, "(%s) Failed to set attrib 0x%x on %s\n", \
155                        __location__, (unsigned int)(sattrib), fname); \
156         }} while (0)
157
158 /*
159   test RAW_OPEN_OPEN
160 */
161 static bool test_open(struct torture_context *tctx, struct smbcli_state *cli)
162 {
163         union smb_open io;
164         union smb_fileinfo finfo;
165         const char *fname = BASEDIR "\\torture_open.txt";
166         NTSTATUS status;
167         int fnum = -1, fnum2;
168         bool ret = true;
169
170         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
171
172         io.openold.level = RAW_OPEN_OPEN;
173         io.openold.in.fname = fname;
174         io.openold.in.open_mode = OPEN_FLAGS_FCB;
175         io.openold.in.search_attrs = 0;
176         status = smb_raw_open(cli->tree, tctx, &io);
177         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
178         fnum = io.openold.out.file.fnum;
179
180         smbcli_unlink(cli->tree, fname);
181         CREATE_FILE;
182         smbcli_close(cli->tree, fnum);
183
184         status = smb_raw_open(cli->tree, tctx, &io);
185         CHECK_STATUS(status, NT_STATUS_OK);
186         fnum = io.openold.out.file.fnum;
187         CHECK_RDWR(fnum, RDWR_RDWR);
188
189         status = smb_raw_open(cli->tree, tctx, &io);
190         CHECK_STATUS(status, NT_STATUS_OK);
191         fnum2 = io.openold.out.file.fnum;
192         CHECK_RDWR(fnum2, RDWR_RDWR);
193         smbcli_close(cli->tree, fnum2);
194         smbcli_close(cli->tree, fnum);
195
196         /* check the read/write modes */
197         io.openold.level = RAW_OPEN_OPEN;
198         io.openold.in.fname = fname;
199         io.openold.in.search_attrs = 0;
200
201         io.openold.in.open_mode = OPEN_FLAGS_OPEN_READ;
202         status = smb_raw_open(cli->tree, tctx, &io);
203         CHECK_STATUS(status, NT_STATUS_OK);
204         fnum = io.openold.out.file.fnum;
205         CHECK_RDWR(fnum, RDWR_RDONLY);
206         smbcli_close(cli->tree, fnum);
207
208         io.openold.in.open_mode = OPEN_FLAGS_OPEN_WRITE;
209         status = smb_raw_open(cli->tree, tctx, &io);
210         CHECK_STATUS(status, NT_STATUS_OK);
211         fnum = io.openold.out.file.fnum;
212         CHECK_RDWR(fnum, RDWR_WRONLY);
213         smbcli_close(cli->tree, fnum);
214
215         io.openold.in.open_mode = OPEN_FLAGS_OPEN_RDWR;
216         status = smb_raw_open(cli->tree, tctx, &io);
217         CHECK_STATUS(status, NT_STATUS_OK);
218         fnum = io.openold.out.file.fnum;
219         CHECK_RDWR(fnum, RDWR_RDWR);
220         smbcli_close(cli->tree, fnum);
221
222         /* check the share modes roughly - not a complete matrix */
223         io.openold.in.open_mode = OPEN_FLAGS_OPEN_RDWR | OPEN_FLAGS_DENY_WRITE;
224         status = smb_raw_open(cli->tree, tctx, &io);
225         CHECK_STATUS(status, NT_STATUS_OK);
226         fnum = io.openold.out.file.fnum;
227         CHECK_RDWR(fnum, RDWR_RDWR);
228         
229         if (io.openold.in.open_mode != io.openold.out.rmode) {
230                 torture_warning(tctx, "(%s) rmode should equal open_mode - 0x%x 0x%x\n",
231                        __location__, io.openold.out.rmode, io.openold.in.open_mode);
232         }
233
234         io.openold.in.open_mode = OPEN_FLAGS_OPEN_RDWR | OPEN_FLAGS_DENY_NONE;
235         status = smb_raw_open(cli->tree, tctx, &io);
236         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
237
238         io.openold.in.open_mode = OPEN_FLAGS_OPEN_READ | OPEN_FLAGS_DENY_NONE;
239         status = smb_raw_open(cli->tree, tctx, &io);
240         CHECK_STATUS(status, NT_STATUS_OK);
241         fnum2 = io.openold.out.file.fnum;
242         CHECK_RDWR(fnum2, RDWR_RDONLY);
243         smbcli_close(cli->tree, fnum);
244         smbcli_close(cli->tree, fnum2);
245
246
247         /* check the returned write time */
248         io.openold.level = RAW_OPEN_OPEN;
249         io.openold.in.fname = fname;
250         io.openold.in.search_attrs = 0;
251         io.openold.in.open_mode = OPEN_FLAGS_OPEN_READ;
252         status = smb_raw_open(cli->tree, tctx, &io);
253         CHECK_STATUS(status, NT_STATUS_OK);
254         fnum = io.openold.out.file.fnum;
255
256         /* check other reply fields */
257         CHECK_TIME(io.openold.out.write_time, write_time);
258         CHECK_ALL_INFO(io.openold.out.size, size);
259         CHECK_ALL_INFO(io.openold.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
260
261 done:
262         smbcli_close(cli->tree, fnum);
263         smbcli_deltree(cli->tree, BASEDIR);
264
265         return ret;
266 }
267
268
269 /*
270   test RAW_OPEN_OPENX
271 */
272 static bool test_openx(struct torture_context *tctx, struct smbcli_state *cli)
273 {
274         union smb_open io;
275         union smb_fileinfo finfo;
276         const char *fname = BASEDIR "\\torture_openx.txt";
277         const char *fname_exe = BASEDIR "\\torture_openx.exe";
278         NTSTATUS status;
279         int fnum = -1, fnum2;
280         bool ret = true;
281         int i;
282         struct timeval tv;
283         struct {
284                 uint16_t open_func;
285                 bool with_file;
286                 NTSTATUS correct_status;
287         } open_funcs[] = {
288                 { OPENX_OPEN_FUNC_OPEN,                           true,  NT_STATUS_OK },
289                 { OPENX_OPEN_FUNC_OPEN,                           false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
290                 { OPENX_OPEN_FUNC_OPEN  | OPENX_OPEN_FUNC_CREATE, true,  NT_STATUS_OK },
291                 { OPENX_OPEN_FUNC_OPEN  | OPENX_OPEN_FUNC_CREATE, false, NT_STATUS_OK },
292                 { OPENX_OPEN_FUNC_FAIL,                           true,  NT_STATUS_DOS(ERRDOS, ERRbadaccess) },
293                 { OPENX_OPEN_FUNC_FAIL,                           false, NT_STATUS_DOS(ERRDOS, ERRbadaccess) },
294                 { OPENX_OPEN_FUNC_FAIL  | OPENX_OPEN_FUNC_CREATE, true,  NT_STATUS_OBJECT_NAME_COLLISION },
295                 { OPENX_OPEN_FUNC_FAIL  | OPENX_OPEN_FUNC_CREATE, false, NT_STATUS_OK },
296                 { OPENX_OPEN_FUNC_TRUNC,                          true,  NT_STATUS_OK },
297                 { OPENX_OPEN_FUNC_TRUNC,                          false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
298                 { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, true,  NT_STATUS_OK },
299                 { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, false, NT_STATUS_OK },
300         };
301
302         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
303
304         io.openx.level = RAW_OPEN_OPENX;
305         io.openx.in.fname = fname;
306         io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
307         io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
308         io.openx.in.search_attrs = 0;
309         io.openx.in.file_attrs = 0;
310         io.openx.in.write_time = 0;
311         io.openx.in.size = 1024*1024;
312         io.openx.in.timeout = 0;
313
314         /* check all combinations of open_func */
315         for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
316                 if (open_funcs[i].with_file) {
317                         fnum = create_complex_file(cli, tctx, fname);
318                         if (fnum == -1) {
319                                 torture_result(tctx, TORTURE_FAIL,
320                                         "Failed to create file %s - %s\n",
321                                         fname, smbcli_errstr(cli->tree));
322                                 ret = false;
323                                 goto done;
324                         }
325                         smbcli_close(cli->tree, fnum);
326                 }
327                 io.openx.in.open_func = open_funcs[i].open_func;
328                 status = smb_raw_open(cli->tree, tctx, &io);
329                 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
330                         torture_result(tctx, TORTURE_FAIL,
331                                 "(%s) incorrect status %s should be %s "
332                                 "(i=%d with_file=%d open_func=0x%x)\n",
333                                 __location__, nt_errstr(status),
334                                 nt_errstr(open_funcs[i].correct_status),
335                                 i, (int)open_funcs[i].with_file,
336                                 open_funcs[i].open_func);
337                         ret = false;
338                 }
339                 if (NT_STATUS_IS_OK(status)) {
340                         smbcli_close(cli->tree, io.openx.out.file.fnum);
341                 }
342                 if (open_funcs[i].with_file) {
343                         smbcli_unlink(cli->tree, fname);
344                 }
345         }
346
347         smbcli_unlink(cli->tree, fname);
348
349         /* check the basic return fields */
350         io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
351         status = smb_raw_open(cli->tree, tctx, &io);
352         CHECK_STATUS(status, NT_STATUS_OK);
353         fnum = io.openx.out.file.fnum;
354
355         CHECK_ALL_INFO(io.openx.out.size, size);
356         CHECK_TIME(io.openx.out.write_time, write_time);
357         CHECK_ALL_INFO(io.openx.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
358         CHECK_VAL(io.openx.out.access, OPENX_MODE_ACCESS_RDWR);
359         CHECK_VAL(io.openx.out.ftype, 0);
360         CHECK_VAL(io.openx.out.devstate, 0);
361         CHECK_VAL(io.openx.out.action, OPENX_ACTION_CREATED);
362         CHECK_VAL(io.openx.out.size, 1024*1024);
363         CHECK_ALL_INFO(io.openx.in.size, size);
364         smbcli_close(cli->tree, fnum);
365         smbcli_unlink(cli->tree, fname);
366
367         /* check the fields when the file already existed */
368         fnum2 = create_complex_file(cli, tctx, fname);
369         if (fnum2 == -1) {
370                 ret = false;
371                 goto done;
372         }
373         smbcli_close(cli->tree, fnum2);
374
375         io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
376         status = smb_raw_open(cli->tree, tctx, &io);
377         CHECK_STATUS(status, NT_STATUS_OK);
378         fnum = io.openx.out.file.fnum;
379
380         CHECK_ALL_INFO(io.openx.out.size, size);
381         CHECK_TIME(io.openx.out.write_time, write_time);
382         CHECK_VAL(io.openx.out.action, OPENX_ACTION_EXISTED);
383         CHECK_VAL(io.openx.out.unknown, 0);
384         CHECK_ALL_INFO(io.openx.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
385         smbcli_close(cli->tree, fnum);
386
387         /* now check the search attrib for hidden files - win2003 ignores this? */
388         SET_ATTRIB(FILE_ATTRIBUTE_HIDDEN);
389         CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN, attrib);
390
391         io.openx.in.search_attrs = FILE_ATTRIBUTE_HIDDEN;
392         status = smb_raw_open(cli->tree, tctx, &io);
393         CHECK_STATUS(status, NT_STATUS_OK);
394         smbcli_close(cli->tree, io.openx.out.file.fnum);
395
396         io.openx.in.search_attrs = 0;
397         status = smb_raw_open(cli->tree, tctx, &io);
398         CHECK_STATUS(status, NT_STATUS_OK);
399         smbcli_close(cli->tree, io.openx.out.file.fnum);
400
401         SET_ATTRIB(FILE_ATTRIBUTE_NORMAL);
402         smbcli_unlink(cli->tree, fname);
403
404         /* and check attrib on create */
405         io.openx.in.open_func = OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE;
406         io.openx.in.search_attrs = 0;
407         io.openx.in.file_attrs = FILE_ATTRIBUTE_SYSTEM;
408         status = smb_raw_open(cli->tree, tctx, &io);
409         CHECK_STATUS(status, NT_STATUS_OK);
410         if (torture_setting_bool(tctx, "samba3", false)) {
411                 CHECK_ALL_INFO(FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE, 
412                                attrib & ~(FILE_ATTRIBUTE_NONINDEXED|
413                                           FILE_ATTRIBUTE_SPARSE));
414         }
415         else {
416                 CHECK_ALL_INFO(FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE, 
417                                attrib & ~(FILE_ATTRIBUTE_NONINDEXED));
418         }
419         smbcli_close(cli->tree, io.openx.out.file.fnum);
420         smbcli_unlink(cli->tree, fname);
421
422         /* check timeout on create - win2003 ignores the timeout! */
423         io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
424         io.openx.in.file_attrs = 0;
425         io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_ALL;
426         status = smb_raw_open(cli->tree, tctx, &io);
427         CHECK_STATUS(status, NT_STATUS_OK);
428         fnum = io.openx.out.file.fnum;
429
430         io.openx.in.timeout = 20000;
431         tv = timeval_current();
432         io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_NONE;
433         status = smb_raw_open(cli->tree, tctx, &io);
434         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
435         if (timeval_elapsed(&tv) > 3.0) {
436                 torture_result(tctx, TORTURE_FAIL,
437                         "(%s) Incorrect timing in openx with timeout "
438                         "- waited %.2f seconds\n",
439                         __location__, timeval_elapsed(&tv));
440                 ret = false;
441         }
442         smbcli_close(cli->tree, fnum);
443         smbcli_unlink(cli->tree, fname);
444
445         /* now this is a really weird one - open for execute implies create?! */
446         io.openx.in.fname = fname;
447         io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
448         io.openx.in.open_mode = OPENX_MODE_ACCESS_EXEC | OPENX_MODE_DENY_NONE;
449         io.openx.in.search_attrs = 0;
450         io.openx.in.open_func = OPENX_OPEN_FUNC_FAIL;
451         io.openx.in.file_attrs = 0;
452         io.openx.in.write_time = 0;
453         io.openx.in.size = 0;
454         io.openx.in.timeout = 0;
455         status = smb_raw_open(cli->tree, tctx, &io);
456         CHECK_STATUS(status, NT_STATUS_OK);
457         smbcli_close(cli->tree, io.openx.out.file.fnum);
458
459         /* check the extended return flag */
460         io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO | OPENX_FLAGS_EXTENDED_RETURN;
461         io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
462         status = smb_raw_open(cli->tree, tctx, &io);
463         CHECK_STATUS(status, NT_STATUS_OK);
464         CHECK_VAL(io.openx.out.access_mask, SEC_STD_ALL);
465         smbcli_close(cli->tree, io.openx.out.file.fnum);
466
467         io.openx.in.fname = "\\A.+,;=[].B";
468         status = smb_raw_open(cli->tree, tctx, &io);
469         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
470
471         /* Check the mapping for open exec. */
472
473         /* First create an .exe file. */
474         smbcli_unlink(cli->tree, fname_exe);
475         fnum = create_complex_file(cli, tctx, fname_exe);
476         smbcli_close(cli->tree, fnum);
477
478         io.openx.level = RAW_OPEN_OPENX;
479         io.openx.in.fname = fname_exe;
480         io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
481         io.openx.in.open_mode = OPENX_MODE_ACCESS_EXEC | OPENX_MODE_DENY_NONE;
482         io.openx.in.search_attrs = 0;
483         io.openx.in.file_attrs = 0;
484         io.openx.in.write_time = 0;
485         io.openx.in.size = 0;
486         io.openx.in.timeout = 0;
487         status = smb_raw_open(cli->tree, tctx, &io);
488         CHECK_STATUS(status, NT_STATUS_OK);
489
490         /* Can we read and write ? */
491         CHECK_RDWR(io.openx.out.file.fnum, RDWR_RDONLY);
492         smbcli_close(cli->tree, io.openx.out.file.fnum);
493         smbcli_unlink(cli->tree, fname);
494
495 done:
496         smbcli_close(cli->tree, fnum);
497         smbcli_deltree(cli->tree, BASEDIR);
498
499         return ret;
500 }
501
502
503 /*
504   test RAW_OPEN_T2OPEN
505
506   many thanks to kukks for a sniff showing how this works with os2->w2k
507 */
508 static bool test_t2open(struct torture_context *tctx, struct smbcli_state *cli)
509 {
510         union smb_open io;
511         union smb_fileinfo finfo;
512         const char *fname1 = BASEDIR "\\torture_t2open_yes.txt";
513         const char *fname2 = BASEDIR "\\torture_t2open_no.txt";
514         const char *fname = BASEDIR "\\torture_t2open_3.txt";
515         NTSTATUS status;
516         int fnum;
517         bool ret = true;
518         int i;
519         struct {
520                 uint16_t open_func;
521                 bool with_file;
522                 NTSTATUS correct_status;
523         } open_funcs[] = {
524                 { OPENX_OPEN_FUNC_OPEN,                           true,  NT_STATUS_OK },
525                 { OPENX_OPEN_FUNC_OPEN,                           false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
526                 { OPENX_OPEN_FUNC_OPEN  | OPENX_OPEN_FUNC_CREATE, true,  NT_STATUS_OK },
527                 { OPENX_OPEN_FUNC_OPEN  | OPENX_OPEN_FUNC_CREATE, false, NT_STATUS_OK },
528                 { OPENX_OPEN_FUNC_FAIL,                           true,  NT_STATUS_OBJECT_NAME_COLLISION },
529                 { OPENX_OPEN_FUNC_FAIL,                           false, NT_STATUS_OBJECT_NAME_COLLISION },
530                 { OPENX_OPEN_FUNC_FAIL  | OPENX_OPEN_FUNC_CREATE, true,  NT_STATUS_OBJECT_NAME_COLLISION },
531                 { OPENX_OPEN_FUNC_FAIL  | OPENX_OPEN_FUNC_CREATE, false, NT_STATUS_OBJECT_NAME_COLLISION },
532                 { OPENX_OPEN_FUNC_TRUNC,                          true,  NT_STATUS_OK },
533                 { OPENX_OPEN_FUNC_TRUNC,                          false, NT_STATUS_OK },
534                 { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, true,  NT_STATUS_OK },
535                 { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, false, NT_STATUS_OK },
536         };
537
538         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
539
540         fnum = create_complex_file(cli, tctx, fname1);
541         if (fnum == -1) {
542                 torture_result(tctx, TORTURE_FAIL,
543                         "(%s): Failed to create file %s - %s\n",
544                         __location__, fname1, smbcli_errstr(cli->tree));
545                 ret = false;
546                 goto done;
547         }
548         smbcli_close(cli->tree, fnum);
549
550         io.t2open.level = RAW_OPEN_T2OPEN;
551         io.t2open.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
552         io.t2open.in.open_mode = OPENX_MODE_DENY_NONE | OPENX_MODE_ACCESS_RDWR;
553         io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
554         io.t2open.in.search_attrs = 0;
555         io.t2open.in.file_attrs = 0;
556         io.t2open.in.write_time = 0;
557         io.t2open.in.size = 0;
558         io.t2open.in.timeout = 0;
559
560         io.t2open.in.num_eas = 3;
561         io.t2open.in.eas = talloc_array(tctx, struct ea_struct, io.t2open.in.num_eas);
562         io.t2open.in.eas[0].flags = 0;
563         io.t2open.in.eas[0].name.s = ".CLASSINFO";
564         io.t2open.in.eas[0].value = data_blob_talloc(tctx, "first value", 11);
565         io.t2open.in.eas[1].flags = 0;
566         io.t2open.in.eas[1].name.s = "EA TWO";
567         io.t2open.in.eas[1].value = data_blob_talloc(tctx, "foo", 3);
568         io.t2open.in.eas[2].flags = 0;
569         io.t2open.in.eas[2].name.s = "X THIRD";
570         io.t2open.in.eas[2].value = data_blob_talloc(tctx, "xy", 2);
571
572         /* check all combinations of open_func */
573         for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
574         again:
575                 if (open_funcs[i].with_file) {
576                         io.t2open.in.fname = fname1;
577                 } else {
578                         io.t2open.in.fname = fname2;
579                 }
580                 io.t2open.in.open_func = open_funcs[i].open_func;
581                 status = smb_raw_open(cli->tree, tctx, &io);
582                 if ((io.t2open.in.num_eas != 0)
583                     && NT_STATUS_EQUAL(status, NT_STATUS_EAS_NOT_SUPPORTED)
584                     && torture_setting_bool(tctx, "samba3", false)) {
585                         torture_warning(tctx, "(%s) EAs not supported, not "
586                                 "treating as fatal in Samba3 test\n",
587                                 __location__);
588                         io.t2open.in.num_eas = 0;
589                         goto again;
590                 }
591
592                 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
593                         torture_result(tctx, TORTURE_FAIL,
594                                 "(%s) incorrect status %s should be %s "
595                                 "(i=%d with_file=%d open_func=0x%x)\n",
596                                  __location__, nt_errstr(status),
597                                 nt_errstr(open_funcs[i].correct_status),
598                                 i, (int)open_funcs[i].with_file,
599                                 open_funcs[i].open_func);
600                         ret = false;
601                 }
602                 if (NT_STATUS_IS_OK(status)) {
603                         smbcli_close(cli->tree, io.t2open.out.file.fnum);
604                 }
605         }
606
607         smbcli_unlink(cli->tree, fname1);
608         smbcli_unlink(cli->tree, fname2);
609
610         /* check the basic return fields */
611         io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
612         io.t2open.in.write_time = 0;
613         io.t2open.in.fname = fname;
614         status = smb_raw_open(cli->tree, tctx, &io);
615         CHECK_STATUS(status, NT_STATUS_OK);
616         fnum = io.t2open.out.file.fnum;
617
618         CHECK_ALL_INFO(io.t2open.out.size, size);
619 #if 0
620         /* windows appears to leak uninitialised memory here */
621         CHECK_VAL(io.t2open.out.write_time, 0);
622 #endif
623         CHECK_ALL_INFO(io.t2open.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
624         CHECK_VAL(io.t2open.out.access, OPENX_MODE_DENY_NONE | OPENX_MODE_ACCESS_RDWR);
625         CHECK_VAL(io.t2open.out.ftype, 0);
626         CHECK_VAL(io.t2open.out.devstate, 0);
627         CHECK_VAL(io.t2open.out.action, OPENX_ACTION_CREATED);
628         smbcli_close(cli->tree, fnum);
629
630         status = torture_check_ea(cli, fname, ".CLASSINFO", "first value");
631         CHECK_STATUS(status, io.t2open.in.num_eas
632                      ? NT_STATUS_OK : NT_STATUS_EAS_NOT_SUPPORTED);
633         status = torture_check_ea(cli, fname, "EA TWO", "foo");
634         CHECK_STATUS(status, io.t2open.in.num_eas
635                      ? NT_STATUS_OK : NT_STATUS_EAS_NOT_SUPPORTED);
636         status = torture_check_ea(cli, fname, "X THIRD", "xy");
637         CHECK_STATUS(status, io.t2open.in.num_eas
638                      ? NT_STATUS_OK : NT_STATUS_EAS_NOT_SUPPORTED);
639
640         /* now check the search attrib for hidden files - win2003 ignores this? */
641         SET_ATTRIB(FILE_ATTRIBUTE_HIDDEN);
642         CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN, attrib);
643
644         status = smb_raw_open(cli->tree, tctx, &io);
645         CHECK_STATUS(status, NT_STATUS_OK);
646         smbcli_close(cli->tree, io.t2open.out.file.fnum);
647
648         status = smb_raw_open(cli->tree, tctx, &io);
649         CHECK_STATUS(status, NT_STATUS_OK);
650         smbcli_close(cli->tree, io.t2open.out.file.fnum);
651
652         SET_ATTRIB(FILE_ATTRIBUTE_NORMAL);
653         smbcli_unlink(cli->tree, fname);
654
655         /* and check attrib on create */
656         io.t2open.in.open_func = OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE;
657         io.t2open.in.file_attrs = FILE_ATTRIBUTE_SYSTEM;
658         status = smb_raw_open(cli->tree, tctx, &io);
659         CHECK_STATUS(status, NT_STATUS_OK);
660
661         /* check timeout on create - win2003 ignores the timeout! */
662         io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
663         io.t2open.in.file_attrs = 0;
664         io.t2open.in.timeout = 20000;
665         io.t2open.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_ALL;
666         status = smb_raw_open(cli->tree, tctx, &io);
667         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
668
669 done:
670         smbcli_close(cli->tree, fnum);
671         smbcli_deltree(cli->tree, BASEDIR);
672
673         return ret;
674 }
675         
676
677 /*
678   test RAW_OPEN_NTCREATEX
679 */
680 static bool test_ntcreatex(struct torture_context *tctx, struct smbcli_state *cli)
681 {
682         union smb_open io;
683         union smb_fileinfo finfo;
684         const char *fname = BASEDIR "\\torture_ntcreatex.txt";
685         const char *dname = BASEDIR "\\torture_ntcreatex.dir";
686         NTSTATUS status;
687         int fnum = -1;
688         bool ret = true;
689         int i;
690         struct {
691                 uint32_t open_disp;
692                 bool with_file;
693                 NTSTATUS correct_status;
694         } open_funcs[] = {
695                 { NTCREATEX_DISP_SUPERSEDE,     true,  NT_STATUS_OK },
696                 { NTCREATEX_DISP_SUPERSEDE,     false, NT_STATUS_OK },
697                 { NTCREATEX_DISP_OPEN,          true,  NT_STATUS_OK },
698                 { NTCREATEX_DISP_OPEN,          false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
699                 { NTCREATEX_DISP_CREATE,        true,  NT_STATUS_OBJECT_NAME_COLLISION },
700                 { NTCREATEX_DISP_CREATE,        false, NT_STATUS_OK },
701                 { NTCREATEX_DISP_OPEN_IF,       true,  NT_STATUS_OK },
702                 { NTCREATEX_DISP_OPEN_IF,       false, NT_STATUS_OK },
703                 { NTCREATEX_DISP_OVERWRITE,     true,  NT_STATUS_OK },
704                 { NTCREATEX_DISP_OVERWRITE,     false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
705                 { NTCREATEX_DISP_OVERWRITE_IF,  true,  NT_STATUS_OK },
706                 { NTCREATEX_DISP_OVERWRITE_IF,  false, NT_STATUS_OK },
707                 { 6,                            true,  NT_STATUS_INVALID_PARAMETER },
708                 { 6,                            false, NT_STATUS_INVALID_PARAMETER },
709         };
710
711         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
712
713         /* reasonable default parameters */
714         io.generic.level = RAW_OPEN_NTCREATEX;
715         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
716         io.ntcreatex.in.root_fid.fnum = 0;
717         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
718         io.ntcreatex.in.alloc_size = 1024*1024;
719         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
720         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
721         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
722         io.ntcreatex.in.create_options = 0;
723         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
724         io.ntcreatex.in.security_flags = 0;
725         io.ntcreatex.in.fname = fname;
726
727         /* test the open disposition */
728         for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
729                 if (open_funcs[i].with_file) {
730                         fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR|O_TRUNC, DENY_NONE);
731                         if (fnum == -1) {
732                                 torture_result(tctx, TORTURE_FAIL,
733                                         "Failed to create file %s - %s\n",
734                                         fname, smbcli_errstr(cli->tree));
735                                 ret = false;
736                                 goto done;
737                         }
738                         smbcli_close(cli->tree, fnum);
739                 }
740                 io.ntcreatex.in.open_disposition = open_funcs[i].open_disp;
741                 status = smb_raw_open(cli->tree, tctx, &io);
742                 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
743                         torture_result(tctx, TORTURE_FAIL,
744                                 "(%s) incorrect status %s should be %s "
745                                 "(i=%d with_file=%d open_disp=%d)\n",
746                                 __location__, nt_errstr(status),
747                                 nt_errstr(open_funcs[i].correct_status),
748                                 i, (int)open_funcs[i].with_file,
749                                 (int)open_funcs[i].open_disp);
750                         ret = false;
751                 }
752                 if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
753                         smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
754                         smbcli_unlink(cli->tree, fname);
755                 }
756         }
757
758         /* basic field testing */
759         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
760
761         status = smb_raw_open(cli->tree, tctx, &io);
762         CHECK_STATUS(status, NT_STATUS_OK);
763         fnum = io.ntcreatex.out.file.fnum;
764
765         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
766         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
767         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
768         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
769         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
770         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
771         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
772         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
773         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
774         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
775         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
776
777         /* check fields when the file already existed */
778         smbcli_close(cli->tree, fnum);
779         smbcli_unlink(cli->tree, fname);
780         fnum = create_complex_file(cli, tctx, fname);
781         if (fnum == -1) {
782                 ret = false;
783                 goto done;
784         }
785         smbcli_close(cli->tree, fnum);
786
787         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
788         status = smb_raw_open(cli->tree, tctx, &io);
789         CHECK_STATUS(status, NT_STATUS_OK);
790         fnum = io.ntcreatex.out.file.fnum;
791
792         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
793         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
794         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
795         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
796         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
797         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
798         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
799         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
800         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
801         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
802         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
803         smbcli_close(cli->tree, fnum);
804         smbcli_unlink(cli->tree, fname);
805
806
807         /* create a directory */
808         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
809         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
810         io.ntcreatex.in.alloc_size = 0;
811         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
812         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
813         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
814         io.ntcreatex.in.create_options = 0;
815         io.ntcreatex.in.fname = dname;
816         fname = dname;
817
818         smbcli_rmdir(cli->tree, fname);
819         smbcli_unlink(cli->tree, fname);
820
821         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
822         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
823         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
824         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
825         status = smb_raw_open(cli->tree, tctx, &io);
826         CHECK_STATUS(status, NT_STATUS_OK);
827         fnum = io.ntcreatex.out.file.fnum;
828
829         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
830         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
831         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
832         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
833         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
834         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
835         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
836         CHECK_VAL(io.ntcreatex.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED, 
837                   FILE_ATTRIBUTE_DIRECTORY);
838         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
839         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
840         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
841         CHECK_VAL(io.ntcreatex.out.is_directory, 1);
842         CHECK_VAL(io.ntcreatex.out.size, 0);
843         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
844         smbcli_unlink(cli->tree, fname);
845         
846
847 done:
848         smbcli_close(cli->tree, fnum);
849         smbcli_deltree(cli->tree, BASEDIR);
850
851         return ret;
852 }
853
854
855 /*
856   test RAW_OPEN_NTTRANS_CREATE
857 */
858 static bool test_nttrans_create(struct torture_context *tctx, struct smbcli_state *cli)
859 {
860         union smb_open io;
861         union smb_fileinfo finfo;
862         const char *fname = BASEDIR "\\torture_ntcreatex.txt";
863         const char *dname = BASEDIR "\\torture_ntcreatex.dir";
864         NTSTATUS status;
865         int fnum = -1;
866         bool ret = true;
867         int i;
868         uint32_t ok_mask, not_supported_mask, invalid_parameter_mask;
869         uint32_t not_a_directory_mask, unexpected_mask;
870         struct {
871                 uint32_t open_disp;
872                 bool with_file;
873                 NTSTATUS correct_status;
874         } open_funcs[] = {
875                 { NTCREATEX_DISP_SUPERSEDE,     true,  NT_STATUS_OK },
876                 { NTCREATEX_DISP_SUPERSEDE,     false, NT_STATUS_OK },
877                 { NTCREATEX_DISP_OPEN,          true,  NT_STATUS_OK },
878                 { NTCREATEX_DISP_OPEN,          false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
879                 { NTCREATEX_DISP_CREATE,        true,  NT_STATUS_OBJECT_NAME_COLLISION },
880                 { NTCREATEX_DISP_CREATE,        false, NT_STATUS_OK },
881                 { NTCREATEX_DISP_OPEN_IF,       true,  NT_STATUS_OK },
882                 { NTCREATEX_DISP_OPEN_IF,       false, NT_STATUS_OK },
883                 { NTCREATEX_DISP_OVERWRITE,     true,  NT_STATUS_OK },
884                 { NTCREATEX_DISP_OVERWRITE,     false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
885                 { NTCREATEX_DISP_OVERWRITE_IF,  true,  NT_STATUS_OK },
886                 { NTCREATEX_DISP_OVERWRITE_IF,  false, NT_STATUS_OK },
887                 { 6,                            true,  NT_STATUS_INVALID_PARAMETER },
888                 { 6,                            false, NT_STATUS_INVALID_PARAMETER },
889         };
890
891         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
892
893         /* reasonable default parameters */
894         io.generic.level = RAW_OPEN_NTTRANS_CREATE;
895         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
896         io.ntcreatex.in.root_fid.fnum = 0;
897         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
898         io.ntcreatex.in.alloc_size = 1024*1024;
899         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
900         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
901         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
902         io.ntcreatex.in.create_options = 0;
903         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
904         io.ntcreatex.in.security_flags = 0;
905         io.ntcreatex.in.fname = fname;
906         io.ntcreatex.in.sec_desc = NULL;
907         io.ntcreatex.in.ea_list = NULL;
908
909         /* test the open disposition */
910         for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
911                 if (open_funcs[i].with_file) {
912                         fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR|O_TRUNC, DENY_NONE);
913                         if (fnum == -1) {
914                                 torture_result(tctx, TORTURE_FAIL,
915                                         "Failed to create file %s - %s\n",
916                                         fname, smbcli_errstr(cli->tree));
917                                 ret = false;
918                                 goto done;
919                         }
920                         smbcli_close(cli->tree, fnum);
921                 }
922                 io.ntcreatex.in.open_disposition = open_funcs[i].open_disp;
923                 status = smb_raw_open(cli->tree, tctx, &io);
924                 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
925                         torture_result(tctx, TORTURE_FAIL,
926                                 "(%s) incorrect status %s should be %s "
927                                 "(i=%d with_file=%d open_disp=%d)\n",
928                                 __location__, nt_errstr(status),
929                                 nt_errstr(open_funcs[i].correct_status),
930                                 i, (int)open_funcs[i].with_file,
931                                 (int)open_funcs[i].open_disp);
932                         ret = false;
933                 }
934                 if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
935                         smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
936                         smbcli_unlink(cli->tree, fname);
937                 }
938         }
939
940         /* basic field testing */
941         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
942
943         status = smb_raw_open(cli->tree, tctx, &io);
944         CHECK_STATUS(status, NT_STATUS_OK);
945         fnum = io.ntcreatex.out.file.fnum;
946
947         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
948         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
949         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
950         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
951         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
952         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
953         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
954         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
955         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
956         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
957         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
958
959         /* check fields when the file already existed */
960         smbcli_close(cli->tree, fnum);
961         smbcli_unlink(cli->tree, fname);
962         fnum = create_complex_file(cli, tctx, fname);
963         if (fnum == -1) {
964                 ret = false;
965                 goto done;
966         }
967         smbcli_close(cli->tree, fnum);
968
969         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
970         status = smb_raw_open(cli->tree, tctx, &io);
971         CHECK_STATUS(status, NT_STATUS_OK);
972         fnum = io.ntcreatex.out.file.fnum;
973
974         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
975         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
976         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
977         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
978         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
979         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
980         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
981         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
982         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
983         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
984         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
985         smbcli_close(cli->tree, fnum);
986
987         /* check no-recall - don't pull a file from tape on a HSM */
988         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_NO_RECALL;
989         status = smb_raw_open(cli->tree, tctx, &io);
990         CHECK_STATUS(status, NT_STATUS_OK);
991         fnum = io.ntcreatex.out.file.fnum;
992
993         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
994         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
995         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
996         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
997         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
998         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
999         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
1000         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
1001         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
1002         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
1003         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
1004         smbcli_close(cli->tree, fnum);
1005
1006         /* Check some create options (these all should be ignored) */
1007         for (i=0; i < 32; i++) {
1008                 uint32_t create_option =
1009                         ((uint32_t)1 << i) & NTCREATEX_OPTIONS_MUST_IGNORE_MASK;
1010                 if (create_option == 0) {
1011                         continue;
1012                 }
1013                 io.ntcreatex.in.create_options = create_option;
1014                 status = smb_raw_open(cli->tree, tctx, &io);
1015                 if (!NT_STATUS_IS_OK(status)) {
1016                         torture_warning(tctx, "ntcreatex create option 0x%08x "
1017                                 "gave %s - should give NT_STATUS_OK\n",
1018                                 create_option, nt_errstr(status));
1019                 }
1020                 CHECK_STATUS(status, NT_STATUS_OK);
1021                 fnum = io.ntcreatex.out.file.fnum;
1022
1023                 CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
1024                 CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
1025                 CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
1026                 CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
1027                 CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
1028                 CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
1029                 CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
1030                 CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
1031                 CHECK_ALL_INFO(io.ntcreatex.out.size, size);
1032                 CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
1033                 CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
1034                 smbcli_close(cli->tree, fnum);
1035         }
1036
1037         io.ntcreatex.in.file_attr = 0;
1038         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1039         io.ntcreatex.in.access_mask     = SEC_FLAG_MAXIMUM_ALLOWED;
1040
1041         /* Check for options that should return NOT_SUPPORTED, OK or INVALID_PARAMETER */
1042         ok_mask = 0;
1043         not_supported_mask = 0;
1044         invalid_parameter_mask = 0;
1045         not_a_directory_mask = 0;
1046         unexpected_mask = 0;
1047         for (i=0; i < 32; i++) {
1048                 uint32_t create_option = (uint32_t)1<<i;
1049                 if (create_option & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
1050                         continue;
1051                 }
1052                 io.ntcreatex.in.create_options = create_option;
1053                 status = smb_raw_open(cli->tree, tctx, &io);
1054                 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
1055                         not_supported_mask |= create_option;
1056                 } else if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1057                         ok_mask |= create_option;
1058                         smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1059                 } else if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1060                         invalid_parameter_mask |= create_option;
1061                 } else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
1062                         not_a_directory_mask |= 1<<i;
1063                 } else {
1064                         unexpected_mask |= 1<<i;
1065                         torture_comment(tctx, "create option 0x%08x returned %s\n",
1066                                         create_option, nt_errstr(status));
1067                 }
1068         }
1069
1070         CHECK_VAL(ok_mask,                0x00efcfce);
1071         CHECK_VAL(not_a_directory_mask,   0x00000001);
1072         CHECK_VAL(not_supported_mask,     0x00002000);
1073         CHECK_VAL(invalid_parameter_mask, 0xff100030);
1074         CHECK_VAL(unexpected_mask,        0x00000000);
1075
1076         smbcli_unlink(cli->tree, fname);
1077
1078
1079         /* create a directory */
1080         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1081         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1082         io.ntcreatex.in.alloc_size = 0;
1083         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1084         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1085         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1086         io.ntcreatex.in.create_options = 0;
1087         io.ntcreatex.in.fname = dname;
1088         fname = dname;
1089
1090         smbcli_rmdir(cli->tree, fname);
1091         smbcli_unlink(cli->tree, fname);
1092
1093         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1094         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1095         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1096         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
1097         status = smb_raw_open(cli->tree, tctx, &io);
1098         CHECK_STATUS(status, NT_STATUS_OK);
1099         fnum = io.ntcreatex.out.file.fnum;
1100
1101         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
1102         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
1103         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
1104         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
1105         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
1106         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
1107         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
1108         CHECK_VAL(io.ntcreatex.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED, 
1109                   FILE_ATTRIBUTE_DIRECTORY);
1110         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
1111         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
1112         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
1113         CHECK_VAL(io.ntcreatex.out.is_directory, 1);
1114         CHECK_VAL(io.ntcreatex.out.size, 0);
1115         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
1116         smbcli_unlink(cli->tree, fname);
1117         
1118
1119 done:
1120         smbcli_close(cli->tree, fnum);
1121         smbcli_deltree(cli->tree, BASEDIR);
1122
1123         return ret;
1124 }
1125
1126 /*
1127   test RAW_OPEN_NTCREATEX with an already opened and byte range locked file
1128
1129   I've got an application that does a similar sequence of ntcreate&x,
1130   locking&x and another ntcreate&x with
1131   open_disposition==NTCREATEX_DISP_OVERWRITE_IF. Windows 2003 allows the
1132   second open.
1133 */
1134 static bool test_ntcreatex_brlocked(struct torture_context *tctx, struct smbcli_state *cli)
1135 {
1136         union smb_open io, io1;
1137         union smb_lock io2;
1138         struct smb_lock_entry lock[1];
1139         const char *fname = BASEDIR "\\torture_ntcreatex.txt";
1140         NTSTATUS status;
1141         bool ret = true;
1142
1143         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1144
1145         torture_comment(tctx, "Testing ntcreatex with a byte range locked file\n");
1146
1147         io.generic.level = RAW_OPEN_NTCREATEX;
1148         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1149         io.ntcreatex.in.root_fid.fnum = 0;
1150         io.ntcreatex.in.access_mask = 0x2019f;
1151         io.ntcreatex.in.alloc_size = 0;
1152         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1153         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1154                 NTCREATEX_SHARE_ACCESS_WRITE;
1155         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1156         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
1157         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
1158         io.ntcreatex.in.security_flags = NTCREATEX_SECURITY_DYNAMIC |
1159                 NTCREATEX_SECURITY_ALL;
1160         io.ntcreatex.in.fname = fname;
1161
1162         status = smb_raw_open(cli->tree, tctx, &io);
1163         CHECK_STATUS(status, NT_STATUS_OK);
1164
1165         io2.lockx.level = RAW_LOCK_LOCKX;
1166         io2.lockx.in.file.fnum = io.ntcreatex.out.file.fnum;
1167         io2.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1168         io2.lockx.in.timeout = 0;
1169         io2.lockx.in.ulock_cnt = 0;
1170         io2.lockx.in.lock_cnt = 1;
1171         lock[0].pid = cli->session->pid;
1172         lock[0].offset = 0;
1173         lock[0].count = 0x1;
1174         io2.lockx.in.locks = &lock[0];
1175         status = smb_raw_lock(cli->tree, &io2);
1176         CHECK_STATUS(status, NT_STATUS_OK);
1177
1178         io1.generic.level = RAW_OPEN_NTCREATEX;
1179         io1.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1180         io1.ntcreatex.in.root_fid.fnum = 0;
1181         io1.ntcreatex.in.access_mask = 0x20196;
1182         io1.ntcreatex.in.alloc_size = 0;
1183         io1.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1184         io1.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1185                 NTCREATEX_SHARE_ACCESS_WRITE;
1186         io1.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1187         io1.ntcreatex.in.create_options = 0;
1188         io1.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
1189         io1.ntcreatex.in.security_flags = NTCREATEX_SECURITY_DYNAMIC |
1190                 NTCREATEX_SECURITY_ALL;
1191         io1.ntcreatex.in.fname = fname;
1192
1193         status = smb_raw_open(cli->tree, tctx, &io1);
1194         CHECK_STATUS(status, NT_STATUS_OK);
1195
1196  done:
1197         smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1198         smbcli_close(cli->tree, io1.ntcreatex.out.file.fnum);
1199         smbcli_deltree(cli->tree, BASEDIR);
1200         return ret;
1201 }
1202
1203 /*
1204   test RAW_OPEN_MKNEW
1205 */
1206 static bool test_mknew(struct torture_context *tctx, struct smbcli_state *cli)
1207 {
1208         union smb_open io;
1209         const char *fname = BASEDIR "\\torture_mknew.txt";
1210         NTSTATUS status;
1211         int fnum = -1;
1212         bool ret = true;
1213         time_t basetime = (time(NULL) + 3600*24*3) & ~1;
1214         union smb_fileinfo finfo;
1215
1216         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1217
1218         io.mknew.level = RAW_OPEN_MKNEW;
1219         io.mknew.in.attrib = 0;
1220         io.mknew.in.write_time = 0;
1221         io.mknew.in.fname = fname;
1222         status = smb_raw_open(cli->tree, tctx, &io);
1223         CHECK_STATUS(status, NT_STATUS_OK);
1224         fnum = io.mknew.out.file.fnum;
1225
1226         status = smb_raw_open(cli->tree, tctx, &io);
1227         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
1228
1229         smbcli_close(cli->tree, fnum);
1230         smbcli_unlink(cli->tree, fname);
1231
1232         /* make sure write_time works */
1233         io.mknew.in.write_time = basetime;
1234         status = smb_raw_open(cli->tree, tctx, &io);
1235         CHECK_STATUS(status, NT_STATUS_OK);
1236         fnum = io.mknew.out.file.fnum;
1237         CHECK_TIME(basetime, write_time);
1238
1239         smbcli_close(cli->tree, fnum);
1240         smbcli_unlink(cli->tree, fname);
1241
1242         /* make sure file_attrs works */
1243         io.mknew.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1244         status = smb_raw_open(cli->tree, tctx, &io);
1245         CHECK_STATUS(status, NT_STATUS_OK);
1246         fnum = io.mknew.out.file.fnum;
1247         CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE, 
1248                        attrib & ~FILE_ATTRIBUTE_NONINDEXED);
1249         
1250 done:
1251         smbcli_close(cli->tree, fnum);
1252         smbcli_deltree(cli->tree, BASEDIR);
1253
1254         return ret;
1255 }
1256
1257
1258 /*
1259   test RAW_OPEN_CREATE
1260 */
1261 static bool test_create(struct torture_context *tctx, struct smbcli_state *cli)
1262 {
1263         union smb_open io;
1264         const char *fname = BASEDIR "\\torture_create.txt";
1265         NTSTATUS status;
1266         int fnum = -1;
1267         bool ret = true;
1268         time_t basetime = (time(NULL) + 3600*24*3) & ~1;
1269         union smb_fileinfo finfo;
1270
1271         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1272
1273         io.create.level = RAW_OPEN_CREATE;
1274         io.create.in.attrib = 0;
1275         io.create.in.write_time = 0;
1276         io.create.in.fname = fname;
1277         status = smb_raw_open(cli->tree, tctx, &io);
1278         CHECK_STATUS(status, NT_STATUS_OK);
1279         fnum = io.create.out.file.fnum;
1280
1281         status = smb_raw_open(cli->tree, tctx, &io);
1282         CHECK_STATUS(status, NT_STATUS_OK);
1283
1284         smbcli_close(cli->tree, io.create.out.file.fnum);
1285         smbcli_close(cli->tree, fnum);
1286         smbcli_unlink(cli->tree, fname);
1287
1288         /* make sure write_time works */
1289         io.create.in.write_time = basetime;
1290         status = smb_raw_open(cli->tree, tctx, &io);
1291         CHECK_STATUS(status, NT_STATUS_OK);
1292         fnum = io.create.out.file.fnum;
1293         CHECK_TIME(basetime, write_time);
1294
1295         smbcli_close(cli->tree, fnum);
1296         smbcli_unlink(cli->tree, fname);
1297
1298         /* make sure file_attrs works */
1299         io.create.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1300         status = smb_raw_open(cli->tree, tctx, &io);
1301         CHECK_STATUS(status, NT_STATUS_OK);
1302         fnum = io.create.out.file.fnum;
1303         CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE, 
1304                        attrib & ~FILE_ATTRIBUTE_NONINDEXED);
1305         
1306 done:
1307         smbcli_close(cli->tree, fnum);
1308         smbcli_deltree(cli->tree, BASEDIR);
1309
1310         return ret;
1311 }
1312
1313
1314 /*
1315   test RAW_OPEN_CTEMP
1316 */
1317 static bool test_ctemp(struct torture_context *tctx, struct smbcli_state *cli)
1318 {
1319         union smb_open io;
1320         NTSTATUS status;
1321         int fnum = -1;
1322         bool ret = true;
1323         time_t basetime = (time(NULL) + 3600*24*3) & ~1;
1324         union smb_fileinfo finfo;
1325         const char *name, *fname = NULL;
1326
1327         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1328
1329         io.ctemp.level = RAW_OPEN_CTEMP;
1330         io.ctemp.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1331         io.ctemp.in.write_time = basetime;
1332         io.ctemp.in.directory = BASEDIR;
1333         status = smb_raw_open(cli->tree, tctx, &io);
1334         CHECK_STATUS(status, NT_STATUS_OK);
1335         fnum = io.ctemp.out.file.fnum;
1336
1337         name = io.ctemp.out.name;
1338
1339         finfo.generic.level = RAW_FILEINFO_NAME_INFO;
1340         finfo.generic.in.file.fnum = fnum;
1341         status = smb_raw_fileinfo(cli->tree, tctx, &finfo);
1342         CHECK_STATUS(status, NT_STATUS_OK);
1343
1344         fname = finfo.name_info.out.fname.s;
1345         torture_comment(tctx, "ctemp name=%s  real name=%s\n", name, fname);
1346
1347 done:
1348         smbcli_close(cli->tree, fnum);
1349         smbcli_deltree(cli->tree, BASEDIR);
1350
1351         return ret;
1352 }
1353
1354
1355 /*
1356   test chained RAW_OPEN_OPENX_READX
1357 */
1358 static bool test_chained(struct torture_context *tctx, struct smbcli_state *cli)
1359 {
1360         union smb_open io;
1361         const char *fname = BASEDIR "\\torture_chained.txt";
1362         NTSTATUS status;
1363         int fnum = -1;
1364         bool ret = true;
1365         const char buf[] = "test";
1366         char buf2[4];
1367
1368         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1369
1370         fnum = create_complex_file(cli, tctx, fname);
1371
1372         smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
1373
1374         smbcli_close(cli->tree, fnum);  
1375
1376         io.openxreadx.level = RAW_OPEN_OPENX_READX;
1377         io.openxreadx.in.fname = fname;
1378         io.openxreadx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
1379         io.openxreadx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
1380         io.openxreadx.in.open_func = OPENX_OPEN_FUNC_OPEN;
1381         io.openxreadx.in.search_attrs = 0;
1382         io.openxreadx.in.file_attrs = 0;
1383         io.openxreadx.in.write_time = 0;
1384         io.openxreadx.in.size = 1024*1024;
1385         io.openxreadx.in.timeout = 0;
1386         
1387         io.openxreadx.in.offset = 0;
1388         io.openxreadx.in.mincnt = sizeof(buf2);
1389         io.openxreadx.in.maxcnt = sizeof(buf2);
1390         io.openxreadx.in.remaining = 0;
1391         io.openxreadx.out.data = (uint8_t *)buf2;
1392
1393         status = smb_raw_open(cli->tree, tctx, &io);
1394         CHECK_STATUS(status, NT_STATUS_OK);
1395         fnum = io.openxreadx.out.file.fnum;
1396
1397         if (memcmp(buf, buf2, MIN(sizeof(buf), sizeof(buf2))) != 0) {
1398                 torture_result(tctx, TORTURE_FAIL,
1399                         "wrong data in reply buffer\n");
1400                 ret = false;
1401         }
1402
1403 done:
1404         smbcli_close(cli->tree, fnum);
1405         smbcli_deltree(cli->tree, BASEDIR);
1406
1407         return ret;
1408 }
1409
1410 /*
1411   test RAW_OPEN_OPENX without a leading slash on the path.
1412   NetApp filers are known to fail on this.
1413   
1414 */
1415 static bool test_no_leading_slash(struct torture_context *tctx, struct smbcli_state *cli)
1416 {
1417         union smb_open io;
1418         const char *fname = BASEDIR "\\torture_no_leading_slash.txt";
1419         NTSTATUS status;
1420         int fnum = -1;
1421         bool ret = true;
1422         const char buf[] = "test";
1423
1424         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1425
1426         smbcli_unlink(cli->tree, fname);
1427
1428         /* Create the file */
1429         fnum = create_complex_file(cli, tctx, fname);
1430         smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
1431         smbcli_close(cli->tree, fnum);  
1432
1433         /* Prepare to open the file using path without leading slash */
1434         io.openx.level = RAW_OPEN_OPENX;
1435         io.openx.in.fname = fname + 1;
1436         io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
1437         io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
1438         io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
1439         io.openx.in.search_attrs = 0;
1440         io.openx.in.file_attrs = 0;
1441         io.openx.in.write_time = 0;
1442         io.openx.in.size = 1024*1024;
1443         io.openx.in.timeout = 0;
1444
1445         status = smb_raw_open(cli->tree, tctx, &io);
1446         CHECK_STATUS(status, NT_STATUS_OK);
1447         fnum = io.openx.out.file.fnum;
1448
1449 done:
1450         smbcli_close(cli->tree, fnum);
1451         smbcli_deltree(cli->tree, BASEDIR);
1452
1453         return ret;
1454 }
1455
1456 /*
1457   test RAW_OPEN_OPENX against an existing directory to
1458   ensure it returns NT_STATUS_FILE_IS_A_DIRECTORY.
1459   Samba 3.2.0 - 3.2.6 are known to fail this.
1460   
1461 */
1462 static bool test_openx_over_dir(struct torture_context *tctx, struct smbcli_state *cli)
1463 {
1464         union smb_open io;
1465         const char *fname = BASEDIR "\\openx_over_dir";
1466         NTSTATUS status;
1467         int d_fnum = -1;
1468         int fnum = -1;
1469         bool ret = true;
1470
1471         ZERO_STRUCT(io);
1472
1473         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1474
1475         /* Create the Directory */
1476         status = create_directory_handle(cli->tree, fname, &d_fnum);
1477         smbcli_close(cli->tree, d_fnum);        
1478
1479         /* Prepare to open the file over the directory. */
1480         io.openx.level = RAW_OPEN_OPENX;
1481         io.openx.in.fname = fname;
1482         io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
1483         io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
1484         io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
1485         io.openx.in.search_attrs = 0;
1486         io.openx.in.file_attrs = 0;
1487         io.openx.in.write_time = 0;
1488         io.openx.in.size = 1024*1024;
1489         io.openx.in.timeout = 0;
1490
1491         status = smb_raw_open(cli->tree, tctx, &io);
1492         CHECK_STATUS(status, NT_STATUS_FILE_IS_A_DIRECTORY);
1493         fnum = io.openx.out.file.fnum;
1494
1495 done:
1496         smbcli_close(cli->tree, fnum);
1497         smbcli_deltree(cli->tree, BASEDIR);
1498
1499         return ret;
1500 }
1501
1502
1503 /* A little torture test to expose a race condition in Samba 3.0.20 ... :-) */
1504
1505 static bool test_raw_open_multi(struct torture_context *tctx, struct smbcli_state *cli_ignored)
1506 {
1507         struct smbcli_state *cli;
1508         TALLOC_CTX *mem_ctx = talloc_init("torture_test_oplock_multi");
1509         const char *fname = "\\test_oplock.dat";
1510         NTSTATUS status;
1511         bool ret = true;
1512         union smb_open io;
1513         struct smbcli_state **clients;
1514         struct smbcli_request **requests;
1515         union smb_open *ios;
1516         const char *host = torture_setting_string(tctx, "host", NULL);
1517         const char *share = torture_setting_string(tctx, "share", NULL);
1518         int i, num_files = 3;
1519         int num_ok = 0;
1520         int num_collision = 0;
1521         
1522         clients = talloc_array(mem_ctx, struct smbcli_state *, num_files);
1523         requests = talloc_array(mem_ctx, struct smbcli_request *, num_files);
1524         ios = talloc_array(mem_ctx, union smb_open, num_files);
1525         if ((tctx->ev == NULL) || (clients == NULL) || (requests == NULL) ||
1526             (ios == NULL)) {
1527                 torture_result(tctx, TORTURE_FAIL, "(%s): talloc failed\n",
1528                                 __location__);
1529                 return false;
1530         }
1531
1532         if (!torture_open_connection_share(mem_ctx, &cli, tctx, host, share, tctx->ev)) {
1533                 return false;
1534         }
1535
1536         cli->tree->session->transport->options.request_timeout = 60;
1537
1538         for (i=0; i<num_files; i++) {
1539                 if (!torture_open_connection_share(mem_ctx, &(clients[i]),
1540                                                    tctx, host, share, tctx->ev)) {
1541                         torture_result(tctx, TORTURE_FAIL,
1542                                        "(%s): Could not open %d'th connection\n",
1543                                        __location__, i);
1544                         return false;
1545                 }
1546                 clients[i]->tree->session->transport->options.request_timeout = 60;
1547         }
1548
1549         /* cleanup */
1550         smbcli_unlink(cli->tree, fname);
1551
1552         /*
1553           base ntcreatex parms
1554         */
1555         io.generic.level = RAW_OPEN_NTCREATEX;
1556         io.ntcreatex.in.root_fid.fnum = 0;
1557         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1558         io.ntcreatex.in.alloc_size = 0;
1559         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1560         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1561                 NTCREATEX_SHARE_ACCESS_WRITE|
1562                 NTCREATEX_SHARE_ACCESS_DELETE;
1563         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1564         io.ntcreatex.in.create_options = 0;
1565         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1566         io.ntcreatex.in.security_flags = 0;
1567         io.ntcreatex.in.fname = fname;
1568         io.ntcreatex.in.flags = 0;
1569
1570         for (i=0; i<num_files; i++) {
1571                 ios[i] = io;
1572                 requests[i] = smb_raw_open_send(clients[i]->tree, &ios[i]);
1573                 if (requests[i] == NULL) {
1574                         torture_result(tctx, TORTURE_FAIL,
1575                                 "(%s): could not send %d'th request\n",
1576                                 __location__, i);
1577                         return false;
1578                 }
1579         }
1580
1581         torture_comment(tctx, "waiting for replies\n");
1582         while (1) {
1583                 bool unreplied = false;
1584                 for (i=0; i<num_files; i++) {
1585                         if (requests[i] == NULL) {
1586                                 continue;
1587                         }
1588                         if (requests[i]->state < SMBCLI_REQUEST_DONE) {
1589                                 unreplied = true;
1590                                 break;
1591                         }
1592                         status = smb_raw_open_recv(requests[i], mem_ctx,
1593                                                    &ios[i]);
1594
1595                         torture_comment(tctx, "File %d returned status %s\n", i,
1596                                   nt_errstr(status));
1597
1598                         if (NT_STATUS_IS_OK(status)) {
1599                                 num_ok += 1;
1600                         } 
1601
1602                         if (NT_STATUS_EQUAL(status,
1603                                             NT_STATUS_OBJECT_NAME_COLLISION)) {
1604                                 num_collision += 1;
1605                         }
1606
1607                         requests[i] = NULL;
1608                 }
1609                 if (!unreplied) {
1610                         break;
1611                 }
1612
1613                 if (tevent_loop_once(tctx->ev) != 0) {
1614                         torture_result(tctx, TORTURE_FAIL,
1615                                 "(%s): tevent_loop_once failed\n", __location__);
1616                         return false;
1617                 }
1618         }
1619
1620         if ((num_ok != 1) || (num_ok + num_collision != num_files)) {
1621                 ret = false;
1622         }
1623
1624         for (i=0; i<num_files; i++) {
1625                 torture_close_connection(clients[i]);
1626         }
1627         talloc_free(mem_ctx);
1628         return ret;
1629 }
1630
1631 /*
1632   test opening for delete on a read-only attribute file.
1633 */
1634 static bool test_open_for_delete(struct torture_context *tctx, struct smbcli_state *cli)
1635 {
1636         union smb_open io;
1637         union smb_fileinfo finfo;
1638         const char *fname = BASEDIR "\\torture_open_for_delete.txt";
1639         NTSTATUS status;
1640         int fnum = -1;
1641         bool ret = true;
1642
1643         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1644
1645         /* reasonable default parameters */
1646         io.generic.level = RAW_OPEN_NTCREATEX;
1647         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1648         io.ntcreatex.in.root_fid.fnum = 0;
1649         io.ntcreatex.in.alloc_size = 0;
1650         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1651         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_READONLY;
1652         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1653         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1654         io.ntcreatex.in.create_options = 0;
1655         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1656         io.ntcreatex.in.security_flags = 0;
1657         io.ntcreatex.in.fname = fname;
1658
1659         /* Create the readonly file. */
1660
1661         status = smb_raw_open(cli->tree, tctx, &io);
1662         CHECK_STATUS(status, NT_STATUS_OK);
1663         fnum = io.ntcreatex.out.file.fnum;
1664
1665         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
1666         io.ntcreatex.in.create_options = 0;
1667         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
1668         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
1669         smbcli_close(cli->tree, fnum);
1670
1671         /* Now try and open for delete only - should succeed. */
1672         io.ntcreatex.in.access_mask = SEC_STD_DELETE;
1673         io.ntcreatex.in.file_attr = 0;
1674         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
1675         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1676         status = smb_raw_open(cli->tree, tctx, &io);
1677         CHECK_STATUS(status, NT_STATUS_OK);
1678
1679         smbcli_unlink(cli->tree, fname);
1680
1681 done:
1682         smbcli_close(cli->tree, fnum);
1683         smbcli_deltree(cli->tree, BASEDIR);
1684
1685         return ret;
1686 }
1687
1688 /*
1689   test chained RAW_OPEN_NTCREATEX_READX
1690   Send chained NTCREATEX_READX on a file that doesn't exist, then create
1691   the file and try again.
1692 */
1693 static bool test_chained_ntcreatex_readx(struct torture_context *tctx, struct smbcli_state *cli)
1694 {
1695         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1696         union smb_open io;
1697         const char *fname = BASEDIR "\\torture_chained.txt";
1698         NTSTATUS status;
1699         int fnum = -1;
1700         bool ret = true;
1701         const char buf[] = "test";
1702         char buf2[4];
1703
1704         ZERO_STRUCT(io);
1705
1706         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1707
1708         torture_comment(tctx, "Checking RAW_NTCREATEX_READX chained on "
1709                               "non-existent file \n");
1710
1711         /* ntcreatex parameters */
1712         io.generic.level = RAW_OPEN_NTCREATEX_READX;
1713         io.ntcreatexreadx.in.flags = 0;
1714         io.ntcreatexreadx.in.root_fid.fnum = 0;
1715         io.ntcreatexreadx.in.access_mask = SEC_FILE_READ_DATA;
1716         io.ntcreatexreadx.in.alloc_size = 0;
1717         io.ntcreatexreadx.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1718         io.ntcreatexreadx.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1719                 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
1720         io.ntcreatexreadx.in.open_disposition = NTCREATEX_DISP_OPEN;
1721         io.ntcreatexreadx.in.create_options = 0;
1722         io.ntcreatexreadx.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
1723         io.ntcreatexreadx.in.security_flags = 0;
1724         io.ntcreatexreadx.in.fname = fname;
1725
1726         /* readx parameters */
1727         io.ntcreatexreadx.in.offset = 0;
1728         io.ntcreatexreadx.in.mincnt = sizeof(buf2);
1729         io.ntcreatexreadx.in.maxcnt = sizeof(buf2);
1730         io.ntcreatexreadx.in.remaining = 0;
1731         io.ntcreatexreadx.out.data = (uint8_t *)buf2;
1732
1733         /* try to open the non-existent file */
1734         status = smb_raw_open(cli->tree, mem_ctx, &io);
1735         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1736         fnum = io.ntcreatexreadx.out.file.fnum;
1737
1738         smbcli_close(cli->tree, fnum);
1739         smbcli_unlink(cli->tree, fname);
1740
1741         torture_comment(tctx, "Checking RAW_NTCREATEX_READX chained on "
1742                               "existing file \n");
1743
1744         fnum = create_complex_file(cli, mem_ctx, fname);
1745         smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
1746         smbcli_close(cli->tree, fnum);
1747
1748         status = smb_raw_open(cli->tree, mem_ctx, &io);
1749         CHECK_STATUS(status, NT_STATUS_OK);
1750         fnum = io.ntcreatexreadx.out.file.fnum;
1751
1752         if (memcmp(buf, buf2, MIN(sizeof(buf), sizeof(buf2))) != 0) {
1753                 torture_result(tctx, TORTURE_FAIL,
1754                         "(%s): wrong data in reply buffer\n", __location__);
1755                 ret = false;
1756         }
1757
1758 done:
1759         smbcli_close(cli->tree, fnum);
1760         smbcli_deltree(cli->tree, BASEDIR);
1761         talloc_free(mem_ctx);
1762
1763         return ret;
1764 }
1765
1766 static bool test_ntcreatex_opendisp_dir(struct torture_context *tctx,
1767                                         struct smbcli_state *cli)
1768 {
1769         const char *dname = BASEDIR "\\torture_ntcreatex_opendisp_dir";
1770         NTSTATUS status;
1771         bool ret = true;
1772         int i;
1773         struct {
1774                 uint32_t open_disp;
1775                 bool dir_exists;
1776                 NTSTATUS correct_status;
1777         } open_funcs_dir[] = {
1778                 { NTCREATEX_DISP_SUPERSEDE,     true,  NT_STATUS_INVALID_PARAMETER },
1779                 { NTCREATEX_DISP_SUPERSEDE,     false, NT_STATUS_INVALID_PARAMETER },
1780                 { NTCREATEX_DISP_OPEN,          true,  NT_STATUS_OK },
1781                 { NTCREATEX_DISP_OPEN,          false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
1782                 { NTCREATEX_DISP_CREATE,        true,  NT_STATUS_OBJECT_NAME_COLLISION },
1783                 { NTCREATEX_DISP_CREATE,        false, NT_STATUS_OK },
1784                 { NTCREATEX_DISP_OPEN_IF,       true,  NT_STATUS_OK },
1785                 { NTCREATEX_DISP_OPEN_IF,       false, NT_STATUS_OK },
1786                 { NTCREATEX_DISP_OVERWRITE,     true,  NT_STATUS_INVALID_PARAMETER },
1787                 { NTCREATEX_DISP_OVERWRITE,     false, NT_STATUS_INVALID_PARAMETER },
1788                 { NTCREATEX_DISP_OVERWRITE_IF,  true,  NT_STATUS_INVALID_PARAMETER },
1789                 { NTCREATEX_DISP_OVERWRITE_IF,  false, NT_STATUS_INVALID_PARAMETER },
1790                 { 6,                            true,  NT_STATUS_INVALID_PARAMETER },
1791                 { 6,                            false, NT_STATUS_INVALID_PARAMETER },
1792         };
1793         union smb_open io;
1794
1795         ZERO_STRUCT(io);
1796         io.generic.level = RAW_OPEN_NTCREATEX;
1797         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1798         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1799         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1800         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
1801         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1802         io.ntcreatex.in.fname = dname;
1803
1804         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1805
1806         smbcli_rmdir(cli->tree, dname);
1807         smbcli_unlink(cli->tree, dname);
1808
1809         /* test the open disposition for directories */
1810         torture_comment(tctx, "Testing open dispositions for directories...\n");
1811
1812         for (i=0; i<ARRAY_SIZE(open_funcs_dir); i++) {
1813                 if (open_funcs_dir[i].dir_exists) {
1814                         status = smbcli_mkdir(cli->tree, dname);
1815                         if (!NT_STATUS_IS_OK(status)) {
1816                                 torture_result(tctx, TORTURE_FAIL,
1817                                         "(%s): Failed to make directory "
1818                                         "%s - %s\n", __location__, dname,
1819                                         smbcli_errstr(cli->tree));
1820                                 ret = false;
1821                                 goto done;
1822                         }
1823                 }
1824
1825                 io.ntcreatex.in.open_disposition = open_funcs_dir[i].open_disp;
1826                 status = smb_raw_open(cli->tree, tctx, &io);
1827                 if (!NT_STATUS_EQUAL(status, open_funcs_dir[i].correct_status)) {
1828                         torture_result(tctx, TORTURE_FAIL,
1829                                 "(%s) incorrect status %s should be %s "
1830                                 "(i=%d dir_exists=%d open_disp=%d)\n",
1831                                 __location__, nt_errstr(status),
1832                                 nt_errstr(open_funcs_dir[i].correct_status),
1833                                 i, (int)open_funcs_dir[i].dir_exists,
1834                                 (int)open_funcs_dir[i].open_disp);
1835                         ret = false;
1836                 }
1837                 if (NT_STATUS_IS_OK(status) || open_funcs_dir[i].dir_exists) {
1838                         smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1839                         smbcli_rmdir(cli->tree, dname);
1840                 }
1841         }
1842
1843 done:
1844         smbcli_deltree(cli->tree, BASEDIR);
1845
1846         return ret;
1847 }
1848
1849 /**
1850  * Test what happens when trying to open a file with directory parameters and
1851  * vice-versa.  Also test that NTCREATEX_OPTIONS_DIRECTORY is treated as
1852  * mandatory and FILE_ATTRIBUTE_DIRECTORY is advisory for directory
1853  * creation/opening.
1854  */
1855 static bool test_ntcreatexdir(struct torture_context *tctx,
1856     struct smbcli_state *cli)
1857 {
1858         union smb_open io;
1859         const char *fname = BASEDIR "\\torture_ntcreatex.txt";
1860         const char *dname = BASEDIR "\\torture_ntcreatex_dir";
1861         NTSTATUS status;
1862         int i;
1863
1864         struct {
1865                 uint32_t open_disp;
1866                 uint32_t file_attr;
1867                 uint32_t create_options;
1868                 NTSTATUS correct_status;
1869         } open_funcs[] = {
1870                 { NTCREATEX_DISP_SUPERSEDE,     0, NTCREATEX_OPTIONS_DIRECTORY,
1871                   NT_STATUS_INVALID_PARAMETER },
1872                 { NTCREATEX_DISP_OPEN,          0, NTCREATEX_OPTIONS_DIRECTORY,
1873                   NT_STATUS_OBJECT_NAME_NOT_FOUND },
1874                 { NTCREATEX_DISP_CREATE,        0, NTCREATEX_OPTIONS_DIRECTORY,
1875                   NT_STATUS_OK },
1876                 { NTCREATEX_DISP_OPEN_IF,       0, NTCREATEX_OPTIONS_DIRECTORY,
1877                   NT_STATUS_OK },
1878                 { NTCREATEX_DISP_OVERWRITE,     0, NTCREATEX_OPTIONS_DIRECTORY,
1879                   NT_STATUS_INVALID_PARAMETER },
1880                 { NTCREATEX_DISP_OVERWRITE_IF,  0, NTCREATEX_OPTIONS_DIRECTORY,
1881                   NT_STATUS_INVALID_PARAMETER },
1882                 { NTCREATEX_DISP_SUPERSEDE,     FILE_ATTRIBUTE_DIRECTORY, 0,
1883                   NT_STATUS_OK },
1884                 { NTCREATEX_DISP_OPEN,          FILE_ATTRIBUTE_DIRECTORY, 0,
1885                   NT_STATUS_OBJECT_NAME_NOT_FOUND },
1886                 { NTCREATEX_DISP_CREATE,        FILE_ATTRIBUTE_DIRECTORY, 0,
1887                   NT_STATUS_OK },
1888                 { NTCREATEX_DISP_OPEN_IF,       FILE_ATTRIBUTE_DIRECTORY, 0,
1889                   NT_STATUS_OK },
1890                 { NTCREATEX_DISP_OVERWRITE,     FILE_ATTRIBUTE_DIRECTORY, 0,
1891                   NT_STATUS_OBJECT_NAME_NOT_FOUND },
1892                 { NTCREATEX_DISP_OVERWRITE_IF,  FILE_ATTRIBUTE_DIRECTORY, 0,
1893                   NT_STATUS_OK },
1894
1895         };
1896
1897         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1898
1899         /* setup some base params. */
1900         io.generic.level = RAW_OPEN_NTCREATEX;
1901         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1902         io.ntcreatex.in.root_fid.fnum = 0;
1903         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1904         io.ntcreatex.in.alloc_size = 0;
1905         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1906         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1907         io.ntcreatex.in.security_flags = 0;
1908         io.ntcreatex.in.fname = fname;
1909
1910         /*
1911          * Test the validity checking for create dispositions, which is done
1912          * against the requested parameters rather than what's actually on
1913          * disk.
1914          */
1915         for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
1916                 io.ntcreatex.in.open_disposition = open_funcs[i].open_disp;
1917                 io.ntcreatex.in.file_attr = open_funcs[i].file_attr;
1918                 io.ntcreatex.in.create_options = open_funcs[i].create_options;
1919                 status = smb_raw_open(cli->tree, tctx, &io);
1920                 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
1921                         torture_result(tctx, TORTURE_FAIL,
1922                                 "(%s) incorrect status %s should be %s "
1923                                 "(i=%d open_disp=%d)\n",
1924                                 __location__, nt_errstr(status),
1925                                 nt_errstr(open_funcs[i].correct_status),
1926                                 i, (int)open_funcs[i].open_disp);
1927                         return false;
1928                 }
1929                 /* Close and delete the file. */
1930                 if (NT_STATUS_IS_OK(status)) {
1931                         if (open_funcs[i].create_options != 0) {
1932                                 /* out attrib should be a directory. */
1933                                 torture_assert_int_equal(tctx,
1934                                     io.ntcreatex.out.attrib,
1935                                     FILE_ATTRIBUTE_DIRECTORY, "should have "
1936                                     "created a directory");
1937
1938                                 smbcli_close(cli->tree,
1939                                     io.ntcreatex.out.file.fnum);
1940
1941                                 /* Make sure unlink fails. */
1942                                 status = smbcli_unlink(cli->tree, fname);
1943                                 torture_assert_ntstatus_equal(tctx, status,
1944                                     NT_STATUS_FILE_IS_A_DIRECTORY,
1945                                     "unlink should fail for a directory");
1946
1947                                 status = smbcli_rmdir(cli->tree, fname);
1948                                 torture_assert_ntstatus_ok(tctx, status,
1949                                     "rmdir failed");
1950                         } else {
1951                                 torture_assert_int_equal(tctx,
1952                                     io.ntcreatex.out.attrib,
1953                                     FILE_ATTRIBUTE_ARCHIVE, "should not have "
1954                                     "created a directory");
1955
1956                                 smbcli_close(cli->tree,
1957                                     io.ntcreatex.out.file.fnum);
1958
1959                                 /* Make sure rmdir fails. */
1960                                 status = smbcli_rmdir(cli->tree, fname);
1961                                 torture_assert_ntstatus_equal(tctx, status,
1962                                     NT_STATUS_NOT_A_DIRECTORY,
1963                                     "rmdir should fail for a file");
1964
1965                                 status = smbcli_unlink(cli->tree, fname);
1966                                 torture_assert_ntstatus_ok(tctx, status,
1967                                     "unlink failed");
1968                         }
1969                 }
1970         }
1971
1972         /* Create a file. */
1973         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1974         io.ntcreatex.in.create_options = 0;
1975         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1976         status = smb_raw_open(cli->tree, tctx, &io);
1977         torture_assert_ntstatus_ok(tctx, status, "Failed to create file.");
1978         smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1979
1980         /* Try and open the file with file_attr_dir and check the error. */
1981         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1982         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1983
1984         status = smb_raw_open(cli->tree, tctx, &io);
1985         torture_assert_ntstatus_ok(tctx, status, "FILE_ATTRIBUTE_DIRECTORY "
1986             "doesn't produce a hard failure.");
1987         smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1988
1989         /* Try and open file with createx_option_dir and check the error. */
1990         io.ntcreatex.in.file_attr = 0;
1991         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1992
1993         status = smb_raw_open(cli->tree, tctx, &io);
1994         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_A_DIRECTORY,
1995             "NTCREATEX_OPTIONS_DIRECTORY will a file from being opened.");
1996         smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1997
1998         /* Delete the file and move onto directory testing. */
1999         smbcli_unlink(cli->tree, fname);
2000
2001         /* Now try some tests on a directory. */
2002         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2003         io.ntcreatex.in.file_attr = 0;
2004         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2005         io.ntcreatex.in.fname = dname;
2006
2007         status = smb_raw_open(cli->tree, tctx, &io);
2008         torture_assert_ntstatus_ok(tctx, status, "Failed to create dir.");
2009
2010         /* out attrib should be a directory. */
2011         torture_assert_int_equal(tctx, io.ntcreatex.out.attrib,
2012             FILE_ATTRIBUTE_DIRECTORY, "should have created a directory");
2013
2014         smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
2015
2016         /* Try and open it with normal attr and check the error. */
2017         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2018         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
2019
2020         status = smb_raw_open(cli->tree, tctx, &io);
2021         torture_assert_ntstatus_ok(tctx, status, "FILE_ATTRIBUTE_NORMAL "
2022             "doesn't produce a hard failure.");
2023         smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
2024
2025         /* Try and open it with file create_options and check the error. */
2026         io.ntcreatex.in.file_attr = 0;
2027         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
2028
2029         status = smb_raw_open(cli->tree, tctx, &io);
2030         torture_assert_ntstatus_equal(tctx, status,
2031             NT_STATUS_FILE_IS_A_DIRECTORY,
2032             "NTCREATEX_OPTIONS_NON_DIRECTORY_FILE should be returned ");
2033         smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
2034
2035         smbcli_deltree(cli->tree, BASEDIR);
2036
2037         return true;
2038 }
2039
2040 /*
2041   test opening with truncate on an already open file
2042   returns share violation and doesn't truncate the file.
2043   Regression test for bug #10671.
2044 */
2045 static bool test_open_for_truncate(struct torture_context *tctx, struct smbcli_state *cli)
2046 {
2047         union smb_open io;
2048         union smb_fileinfo finfo;
2049         const char *fname = BASEDIR "\\torture_open_for_truncate.txt";
2050         NTSTATUS status;
2051         int fnum = -1;
2052         ssize_t val = 0;
2053         char c = '\0';
2054         bool ret = true;
2055
2056         torture_assert(tctx, torture_setup_dir(cli, BASEDIR),
2057                 "Failed to setup up test directory: " BASEDIR);
2058
2059         torture_comment(tctx, "Testing open truncate disposition.\n");
2060
2061         /* reasonable default parameters */
2062         ZERO_STRUCT(io);
2063         io.generic.level = RAW_OPEN_NTCREATEX;
2064         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
2065         io.ntcreatex.in.root_fid.fnum = 0;
2066         io.ntcreatex.in.alloc_size = 0;
2067         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2068         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2069         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2070         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2071         io.ntcreatex.in.create_options = 0;
2072         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2073         io.ntcreatex.in.security_flags = 0;
2074         io.ntcreatex.in.fname = fname;
2075
2076         status = smb_raw_open(cli->tree, tctx, &io);
2077         CHECK_STATUS(status, NT_STATUS_OK);
2078         fnum = io.ntcreatex.out.file.fnum;
2079
2080         /* Write a byte at offset 1k-1. */
2081         val =smbcli_write(cli->tree, fnum, 0, &c, 1023, 1);
2082         torture_assert_int_equal(tctx, val, 1, "write failed\n");
2083
2084         /* Now try and open for read/write with truncate - should fail. */
2085         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_WRITE|SEC_RIGHTS_FILE_READ;
2086         io.ntcreatex.in.file_attr = 0;
2087         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2088                         NTCREATEX_SHARE_ACCESS_WRITE |
2089                         NTCREATEX_SHARE_ACCESS_DELETE;
2090         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
2091         status = smb_raw_open(cli->tree, tctx, &io);
2092         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
2093
2094         /* Ensure file size is still 1k */
2095         finfo.generic.level = RAW_FILEINFO_GETATTRE;
2096         finfo.generic.in.file.fnum = fnum;
2097         status = smb_raw_fileinfo(cli->tree, tctx, &finfo);
2098         CHECK_STATUS(status, NT_STATUS_OK);
2099         CHECK_VAL(finfo.getattre.out.size, 1024);
2100
2101         smbcli_close(cli->tree, fnum);
2102
2103         status = smb_raw_open(cli->tree, tctx, &io);
2104         CHECK_STATUS(status, NT_STATUS_OK);
2105         fnum = io.ntcreatex.out.file.fnum;
2106
2107         /* Ensure truncate actually works */
2108         finfo.generic.level = RAW_FILEINFO_GETATTRE;
2109         finfo.generic.in.file.fnum = fnum;
2110         status = smb_raw_fileinfo(cli->tree, tctx, &finfo);
2111         CHECK_STATUS(status, NT_STATUS_OK);
2112         CHECK_VAL(finfo.getattre.out.size, 0);
2113
2114         smbcli_close(cli->tree, fnum);
2115         smbcli_unlink(cli->tree, fname);
2116
2117 done:
2118         smbcli_close(cli->tree, fnum);
2119         smbcli_deltree(cli->tree, BASEDIR);
2120
2121         return ret;
2122 }
2123
2124 /**
2125  * Test for file size to be 0 after create with FILE_SUPERSEDE
2126  */
2127 static bool test_ntcreatex_supersede(struct torture_context *tctx, struct smbcli_state *cli)
2128 {
2129         union smb_open io;
2130         union smb_setfileinfo sfi;
2131         union smb_fileinfo finfo;
2132         const char *fname = BASEDIR "\\torture_ntcreatex_supersede.txt";
2133         NTSTATUS status;
2134         int fnum = -1;
2135         bool ret = true;
2136
2137         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
2138
2139         /* reasonable default parameters */
2140         io.generic.level = RAW_OPEN_NTCREATEX;
2141         io.ntcreatex.in.flags = 0;
2142         io.ntcreatex.in.root_fid.fnum = 0;
2143         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2144         io.ntcreatex.in.alloc_size = 0;
2145         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2146         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2147         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2148         io.ntcreatex.in.create_options = 0;
2149         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2150         io.ntcreatex.in.security_flags = 0;
2151         io.ntcreatex.in.fname = fname;
2152
2153         status = smb_raw_open(cli->tree, tctx, &io);
2154         CHECK_STATUS(status, NT_STATUS_OK);
2155         fnum = io.ntcreatex.out.file.fnum;
2156
2157         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
2158         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
2159         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
2160         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
2161         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
2162         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
2163         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
2164         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
2165         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
2166         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
2167         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
2168
2169         /* extend the file size */
2170         ZERO_STRUCT(sfi);
2171         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFO;
2172         sfi.generic.in.file.fnum = fnum;
2173         sfi.end_of_file_info.in.size = 512;
2174         status = smb_raw_setfileinfo(cli->tree, &sfi);
2175         CHECK_STATUS(status, NT_STATUS_OK);
2176
2177         /* close the file and re-open with to verify new size */
2178         smbcli_close(cli->tree, fnum);
2179         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
2180         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ;
2181         status = smb_raw_open(cli->tree, tctx, &io);
2182         CHECK_STATUS(status, NT_STATUS_OK);
2183         fnum = io.ntcreatex.out.file.fnum;
2184
2185         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
2186         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
2187         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
2188         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
2189         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
2190         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
2191         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
2192         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
2193         CHECK_VAL(io.ntcreatex.out.size, 512);
2194         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
2195         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
2196
2197         /* close and re-open the file with SUPERSEDE flag */
2198         smbcli_close(cli->tree, fnum);
2199         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_SUPERSEDE;
2200         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ;
2201         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2202         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2203         io.ntcreatex.in.create_options = 0;
2204
2205         status = smb_raw_open(cli->tree, tctx, &io);
2206         CHECK_STATUS(status, NT_STATUS_OK);
2207         fnum = io.ntcreatex.out.file.fnum;
2208
2209         /* The file size in the superseded create response should be 0 */
2210         CHECK_VAL(io.ntcreatex.out.size, 0);
2211         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
2212         CHECK_VAL(io.ntcreatex.out.create_action, FILE_WAS_SUPERSEDED);
2213         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
2214         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
2215         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
2216         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
2217         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
2218         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
2219 done:
2220         smbcli_close(cli->tree, fnum);
2221         smbcli_deltree(cli->tree, BASEDIR);
2222
2223         return ret;
2224 }
2225
2226 /* basic testing of all RAW_OPEN_* calls
2227 */
2228 struct torture_suite *torture_raw_open(TALLOC_CTX *mem_ctx)
2229 {
2230         struct torture_suite *suite = torture_suite_create(mem_ctx, "open");
2231
2232         torture_suite_add_1smb_test(suite, "brlocked", test_ntcreatex_brlocked);
2233         torture_suite_add_1smb_test(suite, "open", test_open);
2234         torture_suite_add_1smb_test(suite, "open-multi", test_raw_open_multi);
2235         torture_suite_add_1smb_test(suite, "openx", test_openx);
2236         torture_suite_add_1smb_test(suite, "ntcreatex", test_ntcreatex);
2237         torture_suite_add_1smb_test(suite, "nttrans-create", test_nttrans_create);
2238         torture_suite_add_1smb_test(suite, "t2open", test_t2open);
2239         torture_suite_add_1smb_test(suite, "mknew", test_mknew);
2240         torture_suite_add_1smb_test(suite, "create", test_create);
2241         torture_suite_add_1smb_test(suite, "ctemp", test_ctemp);
2242         torture_suite_add_1smb_test(suite, "chained-openx", test_chained);
2243         torture_suite_add_1smb_test(suite, "chained-ntcreatex", test_chained_ntcreatex_readx);
2244         torture_suite_add_1smb_test(suite, "no-leading-slash", test_no_leading_slash);
2245         torture_suite_add_1smb_test(suite, "openx-over-dir", test_openx_over_dir);
2246         torture_suite_add_1smb_test(suite, "open-for-delete", test_open_for_delete);
2247         torture_suite_add_1smb_test(suite, "opendisp-dir", test_ntcreatex_opendisp_dir);
2248         torture_suite_add_1smb_test(suite, "ntcreatedir", test_ntcreatexdir);
2249         torture_suite_add_1smb_test(suite, "open-for-truncate", test_open_for_truncate);
2250         torture_suite_add_1smb_test(suite, "ntcreatex_supersede", test_ntcreatex_supersede);
2251
2252         return suite;
2253 }