679a7c24f7e824e5e78a6e3eaf3b4435890bce87
[obnox/samba/samba-obnox.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 (abs(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 (abs(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.alloc_size, 0);
844         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
845         smbcli_unlink(cli->tree, fname);
846         
847
848 done:
849         smbcli_close(cli->tree, fnum);
850         smbcli_deltree(cli->tree, BASEDIR);
851
852         return ret;
853 }
854
855
856 /*
857   test RAW_OPEN_NTTRANS_CREATE
858 */
859 static bool test_nttrans_create(struct torture_context *tctx, struct smbcli_state *cli)
860 {
861         union smb_open io;
862         union smb_fileinfo finfo;
863         const char *fname = BASEDIR "\\torture_ntcreatex.txt";
864         const char *dname = BASEDIR "\\torture_ntcreatex.dir";
865         NTSTATUS status;
866         int fnum = -1;
867         bool ret = true;
868         int i;
869         uint32_t ok_mask, not_supported_mask, invalid_parameter_mask;
870         uint32_t not_a_directory_mask, unexpected_mask;
871         struct {
872                 uint32_t open_disp;
873                 bool with_file;
874                 NTSTATUS correct_status;
875         } open_funcs[] = {
876                 { NTCREATEX_DISP_SUPERSEDE,     true,  NT_STATUS_OK },
877                 { NTCREATEX_DISP_SUPERSEDE,     false, NT_STATUS_OK },
878                 { NTCREATEX_DISP_OPEN,          true,  NT_STATUS_OK },
879                 { NTCREATEX_DISP_OPEN,          false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
880                 { NTCREATEX_DISP_CREATE,        true,  NT_STATUS_OBJECT_NAME_COLLISION },
881                 { NTCREATEX_DISP_CREATE,        false, NT_STATUS_OK },
882                 { NTCREATEX_DISP_OPEN_IF,       true,  NT_STATUS_OK },
883                 { NTCREATEX_DISP_OPEN_IF,       false, NT_STATUS_OK },
884                 { NTCREATEX_DISP_OVERWRITE,     true,  NT_STATUS_OK },
885                 { NTCREATEX_DISP_OVERWRITE,     false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
886                 { NTCREATEX_DISP_OVERWRITE_IF,  true,  NT_STATUS_OK },
887                 { NTCREATEX_DISP_OVERWRITE_IF,  false, NT_STATUS_OK },
888                 { 6,                            true,  NT_STATUS_INVALID_PARAMETER },
889                 { 6,                            false, NT_STATUS_INVALID_PARAMETER },
890         };
891
892         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
893
894         /* reasonable default parameters */
895         io.generic.level = RAW_OPEN_NTTRANS_CREATE;
896         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
897         io.ntcreatex.in.root_fid.fnum = 0;
898         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
899         io.ntcreatex.in.alloc_size = 1024*1024;
900         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
901         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
902         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
903         io.ntcreatex.in.create_options = 0;
904         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
905         io.ntcreatex.in.security_flags = 0;
906         io.ntcreatex.in.fname = fname;
907         io.ntcreatex.in.sec_desc = NULL;
908         io.ntcreatex.in.ea_list = NULL;
909
910         /* test the open disposition */
911         for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
912                 if (open_funcs[i].with_file) {
913                         fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR|O_TRUNC, DENY_NONE);
914                         if (fnum == -1) {
915                                 torture_result(tctx, TORTURE_FAIL,
916                                         "Failed to create file %s - %s\n",
917                                         fname, smbcli_errstr(cli->tree));
918                                 ret = false;
919                                 goto done;
920                         }
921                         smbcli_close(cli->tree, fnum);
922                 }
923                 io.ntcreatex.in.open_disposition = open_funcs[i].open_disp;
924                 status = smb_raw_open(cli->tree, tctx, &io);
925                 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
926                         torture_result(tctx, TORTURE_FAIL,
927                                 "(%s) incorrect status %s should be %s "
928                                 "(i=%d with_file=%d open_disp=%d)\n",
929                                 __location__, nt_errstr(status),
930                                 nt_errstr(open_funcs[i].correct_status),
931                                 i, (int)open_funcs[i].with_file,
932                                 (int)open_funcs[i].open_disp);
933                         ret = false;
934                 }
935                 if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
936                         smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
937                         smbcli_unlink(cli->tree, fname);
938                 }
939         }
940
941         /* basic field testing */
942         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
943
944         status = smb_raw_open(cli->tree, tctx, &io);
945         CHECK_STATUS(status, NT_STATUS_OK);
946         fnum = io.ntcreatex.out.file.fnum;
947
948         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
949         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
950         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
951         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
952         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
953         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
954         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
955         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
956         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
957         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
958         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
959
960         /* check fields when the file already existed */
961         smbcli_close(cli->tree, fnum);
962         smbcli_unlink(cli->tree, fname);
963         fnum = create_complex_file(cli, tctx, fname);
964         if (fnum == -1) {
965                 ret = false;
966                 goto done;
967         }
968         smbcli_close(cli->tree, fnum);
969
970         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
971         status = smb_raw_open(cli->tree, tctx, &io);
972         CHECK_STATUS(status, NT_STATUS_OK);
973         fnum = io.ntcreatex.out.file.fnum;
974
975         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
976         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
977         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
978         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
979         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
980         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
981         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
982         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
983         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
984         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
985         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
986         smbcli_close(cli->tree, fnum);
987
988         /* check no-recall - don't pull a file from tape on a HSM */
989         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_NO_RECALL;
990         status = smb_raw_open(cli->tree, tctx, &io);
991         CHECK_STATUS(status, NT_STATUS_OK);
992         fnum = io.ntcreatex.out.file.fnum;
993
994         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
995         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
996         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
997         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
998         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
999         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
1000         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
1001         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
1002         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
1003         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
1004         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
1005         smbcli_close(cli->tree, fnum);
1006
1007         /* Check some create options (these all should be ignored) */
1008         for (i=0; i < 32; i++) {
1009                 uint32_t create_option = (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 = 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.alloc_size, 0);
1116         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
1117         smbcli_unlink(cli->tree, fname);
1118         
1119
1120 done:
1121         smbcli_close(cli->tree, fnum);
1122         smbcli_deltree(cli->tree, BASEDIR);
1123
1124         return ret;
1125 }
1126
1127 /*
1128   test RAW_OPEN_NTCREATEX with an already opened and byte range locked file
1129
1130   I've got an application that does a similar sequence of ntcreate&x,
1131   locking&x and another ntcreate&x with
1132   open_disposition==NTCREATEX_DISP_OVERWRITE_IF. Windows 2003 allows the
1133   second open.
1134 */
1135 static bool test_ntcreatex_brlocked(struct torture_context *tctx, struct smbcli_state *cli)
1136 {
1137         union smb_open io, io1;
1138         union smb_lock io2;
1139         struct smb_lock_entry lock[1];
1140         const char *fname = BASEDIR "\\torture_ntcreatex.txt";
1141         NTSTATUS status;
1142         bool ret = true;
1143
1144         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1145
1146         torture_comment(tctx, "Testing ntcreatex with a byte range locked file\n");
1147
1148         io.generic.level = RAW_OPEN_NTCREATEX;
1149         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1150         io.ntcreatex.in.root_fid.fnum = 0;
1151         io.ntcreatex.in.access_mask = 0x2019f;
1152         io.ntcreatex.in.alloc_size = 0;
1153         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1154         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1155                 NTCREATEX_SHARE_ACCESS_WRITE;
1156         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1157         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
1158         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
1159         io.ntcreatex.in.security_flags = NTCREATEX_SECURITY_DYNAMIC |
1160                 NTCREATEX_SECURITY_ALL;
1161         io.ntcreatex.in.fname = fname;
1162
1163         status = smb_raw_open(cli->tree, tctx, &io);
1164         CHECK_STATUS(status, NT_STATUS_OK);
1165
1166         io2.lockx.level = RAW_LOCK_LOCKX;
1167         io2.lockx.in.file.fnum = io.ntcreatex.out.file.fnum;
1168         io2.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1169         io2.lockx.in.timeout = 0;
1170         io2.lockx.in.ulock_cnt = 0;
1171         io2.lockx.in.lock_cnt = 1;
1172         lock[0].pid = cli->session->pid;
1173         lock[0].offset = 0;
1174         lock[0].count = 0x1;
1175         io2.lockx.in.locks = &lock[0];
1176         status = smb_raw_lock(cli->tree, &io2);
1177         CHECK_STATUS(status, NT_STATUS_OK);
1178
1179         io1.generic.level = RAW_OPEN_NTCREATEX;
1180         io1.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1181         io1.ntcreatex.in.root_fid.fnum = 0;
1182         io1.ntcreatex.in.access_mask = 0x20196;
1183         io1.ntcreatex.in.alloc_size = 0;
1184         io1.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1185         io1.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1186                 NTCREATEX_SHARE_ACCESS_WRITE;
1187         io1.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1188         io1.ntcreatex.in.create_options = 0;
1189         io1.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
1190         io1.ntcreatex.in.security_flags = NTCREATEX_SECURITY_DYNAMIC |
1191                 NTCREATEX_SECURITY_ALL;
1192         io1.ntcreatex.in.fname = fname;
1193
1194         status = smb_raw_open(cli->tree, tctx, &io1);
1195         CHECK_STATUS(status, NT_STATUS_OK);
1196
1197  done:
1198         smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1199         smbcli_close(cli->tree, io1.ntcreatex.out.file.fnum);
1200         smbcli_deltree(cli->tree, BASEDIR);
1201         return ret;
1202 }
1203
1204 /*
1205   test RAW_OPEN_MKNEW
1206 */
1207 static bool test_mknew(struct torture_context *tctx, struct smbcli_state *cli)
1208 {
1209         union smb_open io;
1210         const char *fname = BASEDIR "\\torture_mknew.txt";
1211         NTSTATUS status;
1212         int fnum = -1;
1213         bool ret = true;
1214         time_t basetime = (time(NULL) + 3600*24*3) & ~1;
1215         union smb_fileinfo finfo;
1216
1217         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1218
1219         io.mknew.level = RAW_OPEN_MKNEW;
1220         io.mknew.in.attrib = 0;
1221         io.mknew.in.write_time = 0;
1222         io.mknew.in.fname = fname;
1223         status = smb_raw_open(cli->tree, tctx, &io);
1224         CHECK_STATUS(status, NT_STATUS_OK);
1225         fnum = io.mknew.out.file.fnum;
1226
1227         status = smb_raw_open(cli->tree, tctx, &io);
1228         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
1229
1230         smbcli_close(cli->tree, fnum);
1231         smbcli_unlink(cli->tree, fname);
1232
1233         /* make sure write_time works */
1234         io.mknew.in.write_time = basetime;
1235         status = smb_raw_open(cli->tree, tctx, &io);
1236         CHECK_STATUS(status, NT_STATUS_OK);
1237         fnum = io.mknew.out.file.fnum;
1238         CHECK_TIME(basetime, write_time);
1239
1240         smbcli_close(cli->tree, fnum);
1241         smbcli_unlink(cli->tree, fname);
1242
1243         /* make sure file_attrs works */
1244         io.mknew.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1245         status = smb_raw_open(cli->tree, tctx, &io);
1246         CHECK_STATUS(status, NT_STATUS_OK);
1247         fnum = io.mknew.out.file.fnum;
1248         CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE, 
1249                        attrib & ~FILE_ATTRIBUTE_NONINDEXED);
1250         
1251 done:
1252         smbcli_close(cli->tree, fnum);
1253         smbcli_deltree(cli->tree, BASEDIR);
1254
1255         return ret;
1256 }
1257
1258
1259 /*
1260   test RAW_OPEN_CREATE
1261 */
1262 static bool test_create(struct torture_context *tctx, struct smbcli_state *cli)
1263 {
1264         union smb_open io;
1265         const char *fname = BASEDIR "\\torture_create.txt";
1266         NTSTATUS status;
1267         int fnum = -1;
1268         bool ret = true;
1269         time_t basetime = (time(NULL) + 3600*24*3) & ~1;
1270         union smb_fileinfo finfo;
1271
1272         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1273
1274         io.create.level = RAW_OPEN_CREATE;
1275         io.create.in.attrib = 0;
1276         io.create.in.write_time = 0;
1277         io.create.in.fname = fname;
1278         status = smb_raw_open(cli->tree, tctx, &io);
1279         CHECK_STATUS(status, NT_STATUS_OK);
1280         fnum = io.create.out.file.fnum;
1281
1282         status = smb_raw_open(cli->tree, tctx, &io);
1283         CHECK_STATUS(status, NT_STATUS_OK);
1284
1285         smbcli_close(cli->tree, io.create.out.file.fnum);
1286         smbcli_close(cli->tree, fnum);
1287         smbcli_unlink(cli->tree, fname);
1288
1289         /* make sure write_time works */
1290         io.create.in.write_time = basetime;
1291         status = smb_raw_open(cli->tree, tctx, &io);
1292         CHECK_STATUS(status, NT_STATUS_OK);
1293         fnum = io.create.out.file.fnum;
1294         CHECK_TIME(basetime, write_time);
1295
1296         smbcli_close(cli->tree, fnum);
1297         smbcli_unlink(cli->tree, fname);
1298
1299         /* make sure file_attrs works */
1300         io.create.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1301         status = smb_raw_open(cli->tree, tctx, &io);
1302         CHECK_STATUS(status, NT_STATUS_OK);
1303         fnum = io.create.out.file.fnum;
1304         CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE, 
1305                        attrib & ~FILE_ATTRIBUTE_NONINDEXED);
1306         
1307 done:
1308         smbcli_close(cli->tree, fnum);
1309         smbcli_deltree(cli->tree, BASEDIR);
1310
1311         return ret;
1312 }
1313
1314
1315 /*
1316   test RAW_OPEN_CTEMP
1317 */
1318 static bool test_ctemp(struct torture_context *tctx, struct smbcli_state *cli)
1319 {
1320         union smb_open io;
1321         NTSTATUS status;
1322         int fnum = -1;
1323         bool ret = true;
1324         time_t basetime = (time(NULL) + 3600*24*3) & ~1;
1325         union smb_fileinfo finfo;
1326         const char *name, *fname = NULL;
1327
1328         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1329
1330         io.ctemp.level = RAW_OPEN_CTEMP;
1331         io.ctemp.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1332         io.ctemp.in.write_time = basetime;
1333         io.ctemp.in.directory = BASEDIR;
1334         status = smb_raw_open(cli->tree, tctx, &io);
1335         CHECK_STATUS(status, NT_STATUS_OK);
1336         fnum = io.ctemp.out.file.fnum;
1337
1338         name = io.ctemp.out.name;
1339
1340         finfo.generic.level = RAW_FILEINFO_NAME_INFO;
1341         finfo.generic.in.file.fnum = fnum;
1342         status = smb_raw_fileinfo(cli->tree, tctx, &finfo);
1343         CHECK_STATUS(status, NT_STATUS_OK);
1344
1345         fname = finfo.name_info.out.fname.s;
1346         torture_comment(tctx, "ctemp name=%s  real name=%s\n", name, fname);
1347
1348 done:
1349         smbcli_close(cli->tree, fnum);
1350         smbcli_deltree(cli->tree, BASEDIR);
1351
1352         return ret;
1353 }
1354
1355
1356 /*
1357   test chained RAW_OPEN_OPENX_READX
1358 */
1359 static bool test_chained(struct torture_context *tctx, struct smbcli_state *cli)
1360 {
1361         union smb_open io;
1362         const char *fname = BASEDIR "\\torture_chained.txt";
1363         NTSTATUS status;
1364         int fnum = -1;
1365         bool ret = true;
1366         const char buf[] = "test";
1367         char buf2[4];
1368
1369         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1370
1371         fnum = create_complex_file(cli, tctx, fname);
1372
1373         smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
1374
1375         smbcli_close(cli->tree, fnum);  
1376
1377         io.openxreadx.level = RAW_OPEN_OPENX_READX;
1378         io.openxreadx.in.fname = fname;
1379         io.openxreadx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
1380         io.openxreadx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
1381         io.openxreadx.in.open_func = OPENX_OPEN_FUNC_OPEN;
1382         io.openxreadx.in.search_attrs = 0;
1383         io.openxreadx.in.file_attrs = 0;
1384         io.openxreadx.in.write_time = 0;
1385         io.openxreadx.in.size = 1024*1024;
1386         io.openxreadx.in.timeout = 0;
1387         
1388         io.openxreadx.in.offset = 0;
1389         io.openxreadx.in.mincnt = sizeof(buf);
1390         io.openxreadx.in.maxcnt = sizeof(buf);
1391         io.openxreadx.in.remaining = 0;
1392         io.openxreadx.out.data = (uint8_t *)buf2;
1393
1394         status = smb_raw_open(cli->tree, tctx, &io);
1395         CHECK_STATUS(status, NT_STATUS_OK);
1396         fnum = io.openxreadx.out.file.fnum;
1397
1398         if (memcmp(buf, buf2, MIN(sizeof(buf), sizeof(buf2))) != 0) {
1399                 torture_result(tctx, TORTURE_FAIL,
1400                         "wrong data in reply buffer\n");
1401                 ret = false;
1402         }
1403
1404 done:
1405         smbcli_close(cli->tree, fnum);
1406         smbcli_deltree(cli->tree, BASEDIR);
1407
1408         return ret;
1409 }
1410
1411 /*
1412   test RAW_OPEN_OPENX without a leading slash on the path.
1413   NetApp filers are known to fail on this.
1414   
1415 */
1416 static bool test_no_leading_slash(struct torture_context *tctx, struct smbcli_state *cli)
1417 {
1418         union smb_open io;
1419         const char *fname = BASEDIR "\\torture_no_leading_slash.txt";
1420         NTSTATUS status;
1421         int fnum = -1;
1422         bool ret = true;
1423         const char buf[] = "test";
1424
1425         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1426
1427         smbcli_unlink(cli->tree, fname);
1428
1429         /* Create the file */
1430         fnum = create_complex_file(cli, tctx, fname);
1431         smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
1432         smbcli_close(cli->tree, fnum);  
1433
1434         /* Prepare to open the file using path without leading slash */
1435         io.openx.level = RAW_OPEN_OPENX;
1436         io.openx.in.fname = fname + 1;
1437         io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
1438         io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
1439         io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
1440         io.openx.in.search_attrs = 0;
1441         io.openx.in.file_attrs = 0;
1442         io.openx.in.write_time = 0;
1443         io.openx.in.size = 1024*1024;
1444         io.openx.in.timeout = 0;
1445
1446         status = smb_raw_open(cli->tree, tctx, &io);
1447         CHECK_STATUS(status, NT_STATUS_OK);
1448         fnum = io.openx.out.file.fnum;
1449
1450 done:
1451         smbcli_close(cli->tree, fnum);
1452         smbcli_deltree(cli->tree, BASEDIR);
1453
1454         return ret;
1455 }
1456
1457 /*
1458   test RAW_OPEN_OPENX against an existing directory to
1459   ensure it returns NT_STATUS_FILE_IS_A_DIRECTORY.
1460   Samba 3.2.0 - 3.2.6 are known to fail this.
1461   
1462 */
1463 static bool test_openx_over_dir(struct torture_context *tctx, struct smbcli_state *cli)
1464 {
1465         union smb_open io;
1466         const char *fname = BASEDIR "\\openx_over_dir";
1467         NTSTATUS status;
1468         int d_fnum = -1;
1469         int fnum = -1;
1470         bool ret = true;
1471
1472         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1473
1474         /* Create the Directory */
1475         status = create_directory_handle(cli->tree, fname, &d_fnum);
1476         smbcli_close(cli->tree, d_fnum);        
1477
1478         /* Prepare to open the file over the directory. */
1479         io.openx.level = RAW_OPEN_OPENX;
1480         io.openx.in.fname = fname;
1481         io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
1482         io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
1483         io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
1484         io.openx.in.search_attrs = 0;
1485         io.openx.in.file_attrs = 0;
1486         io.openx.in.write_time = 0;
1487         io.openx.in.size = 1024*1024;
1488         io.openx.in.timeout = 0;
1489
1490         status = smb_raw_open(cli->tree, tctx, &io);
1491         CHECK_STATUS(status, NT_STATUS_FILE_IS_A_DIRECTORY);
1492         fnum = io.openx.out.file.fnum;
1493
1494 done:
1495         smbcli_close(cli->tree, fnum);
1496         smbcli_deltree(cli->tree, BASEDIR);
1497
1498         return ret;
1499 }
1500
1501
1502 /* A little torture test to expose a race condition in Samba 3.0.20 ... :-) */
1503
1504 static bool test_raw_open_multi(struct torture_context *tctx, struct smbcli_state *cli_ignored)
1505 {
1506         struct smbcli_state *cli;
1507         TALLOC_CTX *mem_ctx = talloc_init("torture_test_oplock_multi");
1508         const char *fname = "\\test_oplock.dat";
1509         NTSTATUS status;
1510         bool ret = true;
1511         union smb_open io;
1512         struct smbcli_state **clients;
1513         struct smbcli_request **requests;
1514         union smb_open *ios;
1515         const char *host = torture_setting_string(tctx, "host", NULL);
1516         const char *share = torture_setting_string(tctx, "share", NULL);
1517         int i, num_files = 3;
1518         int num_ok = 0;
1519         int num_collision = 0;
1520         
1521         clients = talloc_array(mem_ctx, struct smbcli_state *, num_files);
1522         requests = talloc_array(mem_ctx, struct smbcli_request *, num_files);
1523         ios = talloc_array(mem_ctx, union smb_open, num_files);
1524         if ((tctx->ev == NULL) || (clients == NULL) || (requests == NULL) ||
1525             (ios == NULL)) {
1526                 torture_result(tctx, TORTURE_FAIL, "(%s): talloc failed\n",
1527                                 __location__);
1528                 return false;
1529         }
1530
1531         if (!torture_open_connection_share(mem_ctx, &cli, tctx, host, share, tctx->ev)) {
1532                 return false;
1533         }
1534
1535         cli->tree->session->transport->options.request_timeout = 60;
1536
1537         for (i=0; i<num_files; i++) {
1538                 if (!torture_open_connection_share(mem_ctx, &(clients[i]),
1539                                                    tctx, host, share, tctx->ev)) {
1540                         torture_result(tctx, TORTURE_FAIL,
1541                                        "(%s): Could not open %d'th connection\n",
1542                                        __location__, i);
1543                         return false;
1544                 }
1545                 clients[i]->tree->session->transport->options.request_timeout = 60;
1546         }
1547
1548         /* cleanup */
1549         smbcli_unlink(cli->tree, fname);
1550
1551         /*
1552           base ntcreatex parms
1553         */
1554         io.generic.level = RAW_OPEN_NTCREATEX;
1555         io.ntcreatex.in.root_fid.fnum = 0;
1556         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1557         io.ntcreatex.in.alloc_size = 0;
1558         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1559         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1560                 NTCREATEX_SHARE_ACCESS_WRITE|
1561                 NTCREATEX_SHARE_ACCESS_DELETE;
1562         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1563         io.ntcreatex.in.create_options = 0;
1564         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1565         io.ntcreatex.in.security_flags = 0;
1566         io.ntcreatex.in.fname = fname;
1567         io.ntcreatex.in.flags = 0;
1568
1569         for (i=0; i<num_files; i++) {
1570                 ios[i] = io;
1571                 requests[i] = smb_raw_open_send(clients[i]->tree, &ios[i]);
1572                 if (requests[i] == NULL) {
1573                         torture_result(tctx, TORTURE_FAIL,
1574                                 "(%s): could not send %d'th request\n",
1575                                 __location__, i);
1576                         return false;
1577                 }
1578         }
1579
1580         torture_comment(tctx, "waiting for replies\n");
1581         while (1) {
1582                 bool unreplied = false;
1583                 for (i=0; i<num_files; i++) {
1584                         if (requests[i] == NULL) {
1585                                 continue;
1586                         }
1587                         if (requests[i]->state < SMBCLI_REQUEST_DONE) {
1588                                 unreplied = true;
1589                                 break;
1590                         }
1591                         status = smb_raw_open_recv(requests[i], mem_ctx,
1592                                                    &ios[i]);
1593
1594                         torture_comment(tctx, "File %d returned status %s\n", i,
1595                                   nt_errstr(status));
1596
1597                         if (NT_STATUS_IS_OK(status)) {
1598                                 num_ok += 1;
1599                         } 
1600
1601                         if (NT_STATUS_EQUAL(status,
1602                                             NT_STATUS_OBJECT_NAME_COLLISION)) {
1603                                 num_collision += 1;
1604                         }
1605
1606                         requests[i] = NULL;
1607                 }
1608                 if (!unreplied) {
1609                         break;
1610                 }
1611
1612                 if (tevent_loop_once(tctx->ev) != 0) {
1613                         torture_result(tctx, TORTURE_FAIL,
1614                                 "(%s): tevent_loop_once failed\n", __location__);
1615                         return false;
1616                 }
1617         }
1618
1619         if ((num_ok != 1) || (num_ok + num_collision != num_files)) {
1620                 ret = false;
1621         }
1622
1623         for (i=0; i<num_files; i++) {
1624                 torture_close_connection(clients[i]);
1625         }
1626         talloc_free(mem_ctx);
1627         return ret;
1628 }
1629
1630 /*
1631   test opening for delete on a read-only attribute file.
1632 */
1633 static bool test_open_for_delete(struct torture_context *tctx, struct smbcli_state *cli)
1634 {
1635         union smb_open io;
1636         union smb_fileinfo finfo;
1637         const char *fname = BASEDIR "\\torture_open_for_delete.txt";
1638         NTSTATUS status;
1639         int fnum = -1;
1640         bool ret = true;
1641
1642         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1643
1644         /* reasonable default parameters */
1645         io.generic.level = RAW_OPEN_NTCREATEX;
1646         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1647         io.ntcreatex.in.root_fid.fnum = 0;
1648         io.ntcreatex.in.alloc_size = 0;
1649         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1650         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_READONLY;
1651         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1652         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1653         io.ntcreatex.in.create_options = 0;
1654         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1655         io.ntcreatex.in.security_flags = 0;
1656         io.ntcreatex.in.fname = fname;
1657
1658         /* Create the readonly file. */
1659
1660         status = smb_raw_open(cli->tree, tctx, &io);
1661         CHECK_STATUS(status, NT_STATUS_OK);
1662         fnum = io.ntcreatex.out.file.fnum;
1663
1664         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
1665         io.ntcreatex.in.create_options = 0;
1666         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
1667         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
1668         smbcli_close(cli->tree, fnum);
1669
1670         /* Now try and open for delete only - should succeed. */
1671         io.ntcreatex.in.access_mask = SEC_STD_DELETE;
1672         io.ntcreatex.in.file_attr = 0;
1673         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
1674         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1675         status = smb_raw_open(cli->tree, tctx, &io);
1676         CHECK_STATUS(status, NT_STATUS_OK);
1677
1678         smbcli_unlink(cli->tree, fname);
1679
1680 done:
1681         smbcli_close(cli->tree, fnum);
1682         smbcli_deltree(cli->tree, BASEDIR);
1683
1684         return ret;
1685 }
1686
1687 /*
1688   test chained RAW_OPEN_NTCREATEX_READX
1689   Send chained NTCREATEX_READX on a file that doesn't exist, then create
1690   the file and try again.
1691 */
1692 static bool test_chained_ntcreatex_readx(struct torture_context *tctx, struct smbcli_state *cli)
1693 {
1694         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1695         union smb_open io;
1696         const char *fname = BASEDIR "\\torture_chained.txt";
1697         NTSTATUS status;
1698         int fnum = -1;
1699         bool ret = true;
1700         const char buf[] = "test";
1701         char buf2[4];
1702
1703         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1704
1705         torture_comment(tctx, "Checking RAW_NTCREATEX_READX chained on "
1706                               "non-existent file \n");
1707
1708         /* ntcreatex parameters */
1709         io.generic.level = RAW_OPEN_NTCREATEX_READX;
1710         io.ntcreatexreadx.in.flags = 0;
1711         io.ntcreatexreadx.in.root_fid.fnum = 0;
1712         io.ntcreatexreadx.in.access_mask = SEC_FILE_READ_DATA;
1713         io.ntcreatexreadx.in.alloc_size = 0;
1714         io.ntcreatexreadx.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1715         io.ntcreatexreadx.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1716                 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
1717         io.ntcreatexreadx.in.open_disposition = NTCREATEX_DISP_OPEN;
1718         io.ntcreatexreadx.in.create_options = 0;
1719         io.ntcreatexreadx.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
1720         io.ntcreatexreadx.in.security_flags = 0;
1721         io.ntcreatexreadx.in.fname = fname;
1722
1723         /* readx parameters */
1724         io.ntcreatexreadx.in.offset = 0;
1725         io.ntcreatexreadx.in.mincnt = sizeof(buf);
1726         io.ntcreatexreadx.in.maxcnt = sizeof(buf);
1727         io.ntcreatexreadx.in.remaining = 0;
1728         io.ntcreatexreadx.out.data = (uint8_t *)buf2;
1729
1730         /* try to open the non-existent file */
1731         status = smb_raw_open(cli->tree, mem_ctx, &io);
1732         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1733         fnum = io.ntcreatexreadx.out.file.fnum;
1734
1735         smbcli_close(cli->tree, fnum);
1736         smbcli_unlink(cli->tree, fname);
1737
1738         torture_comment(tctx, "Checking RAW_NTCREATEX_READX chained on "
1739                               "existing file \n");
1740
1741         fnum = create_complex_file(cli, mem_ctx, fname);
1742         smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
1743         smbcli_close(cli->tree, fnum);
1744
1745         status = smb_raw_open(cli->tree, mem_ctx, &io);
1746         CHECK_STATUS(status, NT_STATUS_OK);
1747         fnum = io.ntcreatexreadx.out.file.fnum;
1748
1749         if (memcmp(buf, buf2, MIN(sizeof(buf), sizeof(buf2))) != 0) {
1750                 torture_result(tctx, TORTURE_FAIL,
1751                         "(%s): wrong data in reply buffer\n", __location__);
1752                 ret = false;
1753         }
1754
1755 done:
1756         smbcli_close(cli->tree, fnum);
1757         smbcli_deltree(cli->tree, BASEDIR);
1758         talloc_free(mem_ctx);
1759
1760         return ret;
1761 }
1762
1763 static bool test_ntcreatex_opendisp_dir(struct torture_context *tctx,
1764                                         struct smbcli_state *cli)
1765 {
1766         const char *dname = BASEDIR "\\torture_ntcreatex_opendisp_dir";
1767         NTSTATUS status;
1768         bool ret = true;
1769         int i;
1770         struct {
1771                 uint32_t open_disp;
1772                 bool dir_exists;
1773                 NTSTATUS correct_status;
1774         } open_funcs_dir[] = {
1775                 { NTCREATEX_DISP_SUPERSEDE,     true,  NT_STATUS_INVALID_PARAMETER },
1776                 { NTCREATEX_DISP_SUPERSEDE,     false, NT_STATUS_INVALID_PARAMETER },
1777                 { NTCREATEX_DISP_OPEN,          true,  NT_STATUS_OK },
1778                 { NTCREATEX_DISP_OPEN,          false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
1779                 { NTCREATEX_DISP_CREATE,        true,  NT_STATUS_OBJECT_NAME_COLLISION },
1780                 { NTCREATEX_DISP_CREATE,        false, NT_STATUS_OK },
1781                 { NTCREATEX_DISP_OPEN_IF,       true,  NT_STATUS_OK },
1782                 { NTCREATEX_DISP_OPEN_IF,       false, NT_STATUS_OK },
1783                 { NTCREATEX_DISP_OVERWRITE,     true,  NT_STATUS_INVALID_PARAMETER },
1784                 { NTCREATEX_DISP_OVERWRITE,     false, NT_STATUS_INVALID_PARAMETER },
1785                 { NTCREATEX_DISP_OVERWRITE_IF,  true,  NT_STATUS_INVALID_PARAMETER },
1786                 { NTCREATEX_DISP_OVERWRITE_IF,  false, NT_STATUS_INVALID_PARAMETER },
1787                 { 6,                            true,  NT_STATUS_INVALID_PARAMETER },
1788                 { 6,                            false, NT_STATUS_INVALID_PARAMETER },
1789         };
1790         union smb_open io;
1791
1792         ZERO_STRUCT(io);
1793         io.generic.level = RAW_OPEN_NTCREATEX;
1794         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1795         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1796         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1797         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
1798         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1799         io.ntcreatex.in.fname = dname;
1800
1801         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1802
1803         smbcli_rmdir(cli->tree, dname);
1804         smbcli_unlink(cli->tree, dname);
1805
1806         /* test the open disposition for directories */
1807         torture_comment(tctx, "Testing open dispositions for directories...\n");
1808
1809         for (i=0; i<ARRAY_SIZE(open_funcs_dir); i++) {
1810                 if (open_funcs_dir[i].dir_exists) {
1811                         status = smbcli_mkdir(cli->tree, dname);
1812                         if (!NT_STATUS_IS_OK(status)) {
1813                                 torture_result(tctx, TORTURE_FAIL,
1814                                         "(%s): Failed to make directory "
1815                                         "%s - %s\n", __location__, dname,
1816                                         smbcli_errstr(cli->tree));
1817                                 ret = false;
1818                                 goto done;
1819                         }
1820                 }
1821
1822                 io.ntcreatex.in.open_disposition = open_funcs_dir[i].open_disp;
1823                 status = smb_raw_open(cli->tree, tctx, &io);
1824                 if (!NT_STATUS_EQUAL(status, open_funcs_dir[i].correct_status)) {
1825                         torture_result(tctx, TORTURE_FAIL,
1826                                 "(%s) incorrect status %s should be %s "
1827                                 "(i=%d dir_exists=%d open_disp=%d)\n",
1828                                 __location__, nt_errstr(status),
1829                                 nt_errstr(open_funcs_dir[i].correct_status),
1830                                 i, (int)open_funcs_dir[i].dir_exists,
1831                                 (int)open_funcs_dir[i].open_disp);
1832                         ret = false;
1833                 }
1834                 if (NT_STATUS_IS_OK(status) || open_funcs_dir[i].dir_exists) {
1835                         smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1836                         smbcli_rmdir(cli->tree, dname);
1837                 }
1838         }
1839
1840 done:
1841         smbcli_deltree(cli->tree, BASEDIR);
1842
1843         return ret;
1844 }
1845
1846 /**
1847  * Test what happens when trying to open a file with directory parameters and
1848  * vice-versa.  Also test that NTCREATEX_OPTIONS_DIRECTORY is treated as
1849  * mandatory and FILE_ATTRIBUTE_DIRECTORY is advisory for directory
1850  * creation/opening.
1851  */
1852 static bool test_ntcreatexdir(struct torture_context *tctx,
1853     struct smbcli_state *cli)
1854 {
1855         union smb_open io;
1856         const char *fname = BASEDIR "\\torture_ntcreatex.txt";
1857         const char *dname = BASEDIR "\\torture_ntcreatex_dir";
1858         NTSTATUS status;
1859         int i;
1860
1861         struct {
1862                 uint32_t open_disp;
1863                 uint32_t file_attr;
1864                 uint32_t create_options;
1865                 NTSTATUS correct_status;
1866         } open_funcs[] = {
1867                 { NTCREATEX_DISP_SUPERSEDE,     0, NTCREATEX_OPTIONS_DIRECTORY,
1868                   NT_STATUS_INVALID_PARAMETER },
1869                 { NTCREATEX_DISP_OPEN,          0, NTCREATEX_OPTIONS_DIRECTORY,
1870                   NT_STATUS_OBJECT_NAME_NOT_FOUND },
1871                 { NTCREATEX_DISP_CREATE,        0, NTCREATEX_OPTIONS_DIRECTORY,
1872                   NT_STATUS_OK },
1873                 { NTCREATEX_DISP_OPEN_IF,       0, NTCREATEX_OPTIONS_DIRECTORY,
1874                   NT_STATUS_OK },
1875                 { NTCREATEX_DISP_OVERWRITE,     0, NTCREATEX_OPTIONS_DIRECTORY,
1876                   NT_STATUS_INVALID_PARAMETER },
1877                 { NTCREATEX_DISP_OVERWRITE_IF,  0, NTCREATEX_OPTIONS_DIRECTORY,
1878                   NT_STATUS_INVALID_PARAMETER },
1879                 { NTCREATEX_DISP_SUPERSEDE,     FILE_ATTRIBUTE_DIRECTORY, 0,
1880                   NT_STATUS_OK },
1881                 { NTCREATEX_DISP_OPEN,          FILE_ATTRIBUTE_DIRECTORY, 0,
1882                   NT_STATUS_OBJECT_NAME_NOT_FOUND },
1883                 { NTCREATEX_DISP_CREATE,        FILE_ATTRIBUTE_DIRECTORY, 0,
1884                   NT_STATUS_OK },
1885                 { NTCREATEX_DISP_OPEN_IF,       FILE_ATTRIBUTE_DIRECTORY, 0,
1886                   NT_STATUS_OK },
1887                 { NTCREATEX_DISP_OVERWRITE,     FILE_ATTRIBUTE_DIRECTORY, 0,
1888                   NT_STATUS_OBJECT_NAME_NOT_FOUND },
1889                 { NTCREATEX_DISP_OVERWRITE_IF,  FILE_ATTRIBUTE_DIRECTORY, 0,
1890                   NT_STATUS_OK },
1891
1892         };
1893
1894         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1895
1896         /* setup some base params. */
1897         io.generic.level = RAW_OPEN_NTCREATEX;
1898         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1899         io.ntcreatex.in.root_fid.fnum = 0;
1900         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1901         io.ntcreatex.in.alloc_size = 0;
1902         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1903         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1904         io.ntcreatex.in.security_flags = 0;
1905         io.ntcreatex.in.fname = fname;
1906
1907         /*
1908          * Test the validity checking for create dispositions, which is done
1909          * against the requested parameters rather than what's actually on
1910          * disk.
1911          */
1912         for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
1913                 io.ntcreatex.in.open_disposition = open_funcs[i].open_disp;
1914                 io.ntcreatex.in.file_attr = open_funcs[i].file_attr;
1915                 io.ntcreatex.in.create_options = open_funcs[i].create_options;
1916                 status = smb_raw_open(cli->tree, tctx, &io);
1917                 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
1918                         torture_result(tctx, TORTURE_FAIL,
1919                                 "(%s) incorrect status %s should be %s "
1920                                 "(i=%d open_disp=%d)\n",
1921                                 __location__, nt_errstr(status),
1922                                 nt_errstr(open_funcs[i].correct_status),
1923                                 i, (int)open_funcs[i].open_disp);
1924                         return false;
1925                 }
1926                 /* Close and delete the file. */
1927                 if (NT_STATUS_IS_OK(status)) {
1928                         if (open_funcs[i].create_options != 0) {
1929                                 /* out attrib should be a directory. */
1930                                 torture_assert_int_equal(tctx,
1931                                     io.ntcreatex.out.attrib,
1932                                     FILE_ATTRIBUTE_DIRECTORY, "should have "
1933                                     "created a directory");
1934
1935                                 smbcli_close(cli->tree,
1936                                     io.ntcreatex.out.file.fnum);
1937
1938                                 /* Make sure unlink fails. */
1939                                 status = smbcli_unlink(cli->tree, fname);
1940                                 torture_assert_ntstatus_equal(tctx, status,
1941                                     NT_STATUS_FILE_IS_A_DIRECTORY,
1942                                     "unlink should fail for a directory");
1943
1944                                 status = smbcli_rmdir(cli->tree, fname);
1945                                 torture_assert_ntstatus_ok(tctx, status,
1946                                     "rmdir failed");
1947                         } else {
1948                                 torture_assert_int_equal(tctx,
1949                                     io.ntcreatex.out.attrib,
1950                                     FILE_ATTRIBUTE_ARCHIVE, "should not have "
1951                                     "created a directory");
1952
1953                                 smbcli_close(cli->tree,
1954                                     io.ntcreatex.out.file.fnum);
1955
1956                                 /* Make sure rmdir fails. */
1957                                 status = smbcli_rmdir(cli->tree, fname);
1958                                 torture_assert_ntstatus_equal(tctx, status,
1959                                     NT_STATUS_NOT_A_DIRECTORY,
1960                                     "rmdir should fail for a file");
1961
1962                                 status = smbcli_unlink(cli->tree, fname);
1963                                 torture_assert_ntstatus_ok(tctx, status,
1964                                     "unlink failed");
1965                         }
1966                 }
1967         }
1968
1969         /* Create a file. */
1970         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1971         io.ntcreatex.in.create_options = 0;
1972         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1973         status = smb_raw_open(cli->tree, tctx, &io);
1974         torture_assert_ntstatus_ok(tctx, status, "Failed to create file.");
1975         smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1976
1977         /* Try and open the file with file_attr_dir and check the error. */
1978         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1979         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1980
1981         status = smb_raw_open(cli->tree, tctx, &io);
1982         torture_assert_ntstatus_ok(tctx, status, "FILE_ATTRIBUTE_DIRECTORY "
1983             "doesn't produce a hard failure.");
1984         smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1985
1986         /* Try and open file with createx_option_dir and check the error. */
1987         io.ntcreatex.in.file_attr = 0;
1988         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1989
1990         status = smb_raw_open(cli->tree, tctx, &io);
1991         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_A_DIRECTORY,
1992             "NTCREATEX_OPTIONS_DIRECTORY will a file from being opened.");
1993         smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1994
1995         /* Delete the file and move onto directory testing. */
1996         smbcli_unlink(cli->tree, fname);
1997
1998         /* Now try some tests on a directory. */
1999         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2000         io.ntcreatex.in.file_attr = 0;
2001         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2002         io.ntcreatex.in.fname = dname;
2003
2004         status = smb_raw_open(cli->tree, tctx, &io);
2005         torture_assert_ntstatus_ok(tctx, status, "Failed to create dir.");
2006
2007         /* out attrib should be a directory. */
2008         torture_assert_int_equal(tctx, io.ntcreatex.out.attrib,
2009             FILE_ATTRIBUTE_DIRECTORY, "should have created a directory");
2010
2011         smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
2012
2013         /* Try and open it with normal attr and check the error. */
2014         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2015         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
2016
2017         status = smb_raw_open(cli->tree, tctx, &io);
2018         torture_assert_ntstatus_ok(tctx, status, "FILE_ATTRIBUTE_NORMAL "
2019             "doesn't produce a hard failure.");
2020         smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
2021
2022         /* Try and open it with file create_options and check the error. */
2023         io.ntcreatex.in.file_attr = 0;
2024         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
2025
2026         status = smb_raw_open(cli->tree, tctx, &io);
2027         torture_assert_ntstatus_equal(tctx, status,
2028             NT_STATUS_FILE_IS_A_DIRECTORY,
2029             "NTCREATEX_OPTIONS_NON_DIRECTORY_FILE should be returned ");
2030         smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
2031
2032         smbcli_deltree(cli->tree, BASEDIR);
2033
2034         return true;
2035 }
2036
2037 /*
2038   test opening with truncate on an already open file
2039   returns share violation and doesn't truncate the file.
2040   Regression test for bug #10671.
2041 */
2042 static bool test_open_for_truncate(struct torture_context *tctx, struct smbcli_state *cli)
2043 {
2044         union smb_open io;
2045         union smb_fileinfo finfo;
2046         const char *fname = BASEDIR "\\torture_open_for_truncate.txt";
2047         NTSTATUS status;
2048         int fnum = -1;
2049         ssize_t val = 0;
2050         char c = '\0';
2051         bool ret = true;
2052
2053         torture_assert(tctx, torture_setup_dir(cli, BASEDIR),
2054                 "Failed to setup up test directory: " BASEDIR);
2055
2056         torture_comment(tctx, "Testing open truncate disposition.\n");
2057
2058         /* reasonable default parameters */
2059         ZERO_STRUCT(io);
2060         io.generic.level = RAW_OPEN_NTCREATEX;
2061         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
2062         io.ntcreatex.in.root_fid.fnum = 0;
2063         io.ntcreatex.in.alloc_size = 0;
2064         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2065         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2066         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2067         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2068         io.ntcreatex.in.create_options = 0;
2069         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2070         io.ntcreatex.in.security_flags = 0;
2071         io.ntcreatex.in.fname = fname;
2072
2073         status = smb_raw_open(cli->tree, tctx, &io);
2074         CHECK_STATUS(status, NT_STATUS_OK);
2075         fnum = io.ntcreatex.out.file.fnum;
2076
2077         /* Write a byte at offset 1k-1. */
2078         val =smbcli_write(cli->tree, fnum, 0, &c, 1023, 1);
2079         torture_assert_int_equal(tctx, val, 1, "write failed\n");
2080
2081         /* Now try and open for read/write with truncate - should fail. */
2082         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_WRITE|SEC_RIGHTS_FILE_READ;
2083         io.ntcreatex.in.file_attr = 0;
2084         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2085                         NTCREATEX_SHARE_ACCESS_WRITE |
2086                         NTCREATEX_SHARE_ACCESS_DELETE;
2087         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
2088         status = smb_raw_open(cli->tree, tctx, &io);
2089         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
2090
2091         /* Ensure file size is still 1k */
2092         finfo.generic.level = RAW_FILEINFO_GETATTRE;
2093         finfo.generic.in.file.fnum = fnum;
2094         status = smb_raw_fileinfo(cli->tree, tctx, &finfo);
2095         CHECK_STATUS(status, NT_STATUS_OK);
2096         CHECK_VAL(finfo.getattre.out.size, 1024);
2097
2098         smbcli_close(cli->tree, fnum);
2099
2100         status = smb_raw_open(cli->tree, tctx, &io);
2101         CHECK_STATUS(status, NT_STATUS_OK);
2102         fnum = io.ntcreatex.out.file.fnum;
2103
2104         /* Ensure truncate actually works */
2105         finfo.generic.level = RAW_FILEINFO_GETATTRE;
2106         finfo.generic.in.file.fnum = fnum;
2107         status = smb_raw_fileinfo(cli->tree, tctx, &finfo);
2108         CHECK_STATUS(status, NT_STATUS_OK);
2109         CHECK_VAL(finfo.getattre.out.size, 0);
2110
2111         smbcli_close(cli->tree, fnum);
2112         smbcli_unlink(cli->tree, fname);
2113
2114 done:
2115         smbcli_close(cli->tree, fnum);
2116         smbcli_deltree(cli->tree, BASEDIR);
2117
2118         return ret;
2119 }
2120
2121
2122 /* basic testing of all RAW_OPEN_* calls
2123 */
2124 struct torture_suite *torture_raw_open(TALLOC_CTX *mem_ctx)
2125 {
2126         struct torture_suite *suite = torture_suite_create(mem_ctx, "open");
2127
2128         torture_suite_add_1smb_test(suite, "brlocked", test_ntcreatex_brlocked);
2129         torture_suite_add_1smb_test(suite, "open", test_open);
2130         torture_suite_add_1smb_test(suite, "open-multi", test_raw_open_multi);
2131         torture_suite_add_1smb_test(suite, "openx", test_openx);
2132         torture_suite_add_1smb_test(suite, "ntcreatex", test_ntcreatex);
2133         torture_suite_add_1smb_test(suite, "nttrans-create", test_nttrans_create);
2134         torture_suite_add_1smb_test(suite, "t2open", test_t2open);
2135         torture_suite_add_1smb_test(suite, "mknew", test_mknew);
2136         torture_suite_add_1smb_test(suite, "create", test_create);
2137         torture_suite_add_1smb_test(suite, "ctemp", test_ctemp);
2138         torture_suite_add_1smb_test(suite, "chained-openx", test_chained);
2139         torture_suite_add_1smb_test(suite, "chained-ntcreatex", test_chained_ntcreatex_readx);
2140         torture_suite_add_1smb_test(suite, "no-leading-slash", test_no_leading_slash);
2141         torture_suite_add_1smb_test(suite, "openx-over-dir", test_openx_over_dir);
2142         torture_suite_add_1smb_test(suite, "open-for-delete", test_open_for_delete);
2143         torture_suite_add_1smb_test(suite, "opendisp-dir", test_ntcreatex_opendisp_dir);
2144         torture_suite_add_1smb_test(suite, "ntcreatedir", test_ntcreatexdir);
2145         torture_suite_add_1smb_test(suite, "open-for-truncate", test_open_for_truncate);
2146
2147         return suite;
2148 }