1346a075f2c440210c72d68252361c2b9a57c736
[jelmer/samba4-debian.git] / source / 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 2 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, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22 #include "torture/torture.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "system/time.h"
25 #include "system/filesys.h"
26 #include "librpc/gen_ndr/ndr_security.h"
27 #include "lib/events/events.h"
28 #include "libcli/libcli.h"
29
30 /* enum for whether reads/writes are possible on a file */
31 enum rdwr_mode {RDWR_NONE, RDWR_RDONLY, RDWR_WRONLY, RDWR_RDWR};
32
33 #define BASEDIR "\\rawopen"
34
35 /*
36   check if a open file can be read/written
37 */
38 static enum rdwr_mode check_rdwr(struct smbcli_tree *tree, int fnum)
39 {
40         uint8_t c = 1;
41         BOOL can_read  = (smbcli_read(tree, fnum, &c, 0, 1) == 1);
42         BOOL can_write = (smbcli_write(tree, fnum, 0, &c, 0, 1) == 1);
43         if ( can_read &&  can_write) return RDWR_RDWR;
44         if ( can_read && !can_write) return RDWR_RDONLY;
45         if (!can_read &&  can_write) return RDWR_WRONLY;
46         return RDWR_NONE;
47 }
48
49 /*
50   describe a RDWR mode as a string
51 */
52 static const char *rdwr_string(enum rdwr_mode m)
53 {
54         switch (m) {
55         case RDWR_NONE: return "NONE";
56         case RDWR_RDONLY: return "RDONLY";
57         case RDWR_WRONLY: return "WRONLY";
58         case RDWR_RDWR: return "RDWR";
59         }
60         return "-";
61 }
62
63 #define CHECK_STATUS(status, correct) do { \
64         if (!NT_STATUS_EQUAL(status, correct)) { \
65                 printf("(%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, mem_ctx, fname); \
73         if (fnum == -1) { \
74                 printf("(%s) Failed to create %s - %s\n", __location__, fname, smbcli_errstr(cli->tree)); \
75                 ret = False; \
76                 goto done; \
77         }} while (0)
78
79 #define CHECK_RDWR(fnum, correct) do { \
80         enum rdwr_mode m = check_rdwr(cli->tree, fnum); \
81         if (m != correct) { \
82                 printf("(%s) Incorrect readwrite mode %s - expected %s\n", \
83                        __location__, rdwr_string(m), rdwr_string(correct)); \
84                 ret = False; \
85         }} while (0)
86
87 #define CHECK_TIME(t, field) do { \
88         time_t t1, t2; \
89         finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
90         finfo.all_info.in.fname = fname; \
91         status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo); \
92         CHECK_STATUS(status, NT_STATUS_OK); \
93         t1 = t & ~1; \
94         t2 = nt_time_to_unix(finfo.all_info.out.field) & ~1; \
95         if (ABS(t1-t2) > 2) { \
96                 printf("(%s) wrong time for field %s  %s - %s\n", \
97                        __location__, #field, \
98                        timestring(mem_ctx, t1), \
99                        timestring(mem_ctx, t2)); \
100                 dump_all_info(mem_ctx, &finfo); \
101                 ret = False; \
102         }} while (0)
103
104 #define CHECK_NTTIME(t, field) do { \
105         NTTIME t2; \
106         finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
107         finfo.all_info.in.fname = fname; \
108         status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo); \
109         CHECK_STATUS(status, NT_STATUS_OK); \
110         t2 = finfo.all_info.out.field; \
111         if (t != t2) { \
112                 printf("(%s) wrong time for field %s  %s - %s\n", \
113                        __location__, #field, \
114                        nt_time_string(mem_ctx, t), \
115                        nt_time_string(mem_ctx, t2)); \
116                 dump_all_info(mem_ctx, &finfo); \
117                 ret = False; \
118         }} while (0)
119
120 #define CHECK_ALL_INFO(v, field) do { \
121         finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
122         finfo.all_info.in.fname = fname; \
123         status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo); \
124         CHECK_STATUS(status, NT_STATUS_OK); \
125         if ((v) != (finfo.all_info.out.field)) { \
126                 printf("(%s) wrong value for field %s  0x%x - 0x%x\n", \
127                        __location__, #field, (int)v, (int)(finfo.all_info.out.field)); \
128                 dump_all_info(mem_ctx, &finfo); \
129                 ret = False; \
130         }} while (0)
131
132 #define CHECK_VAL(v, correct) do { \
133         if ((v) != (correct)) { \
134                 printf("(%s) wrong value for %s  0x%x - should be 0x%x\n", \
135                        __location__, #v, (int)(v), (int)correct); \
136                 ret = False; \
137         }} while (0)
138
139 #define SET_ATTRIB(sattrib) do { \
140         union smb_setfileinfo sfinfo; \
141         sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION; \
142         sfinfo.generic.file.fname = fname; \
143         ZERO_STRUCT(sfinfo.basic_info.in); \
144         sfinfo.basic_info.in.attrib = sattrib; \
145         status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
146         if (!NT_STATUS_IS_OK(status)) { \
147                 printf("(%s) Failed to set attrib 0x%x on %s\n", \
148                        __location__, sattrib, fname); \
149         }} while (0)
150
151 /*
152   test RAW_OPEN_OPEN
153 */
154 static BOOL test_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
155 {
156         union smb_open io;
157         union smb_fileinfo finfo;
158         const char *fname = BASEDIR "\\torture_open.txt";
159         NTSTATUS status;
160         int fnum = -1, fnum2;
161         BOOL ret = True;
162
163         printf("Checking RAW_OPEN_OPEN\n");
164
165         io.openold.level = RAW_OPEN_OPEN;
166         io.openold.in.fname = fname;
167         io.openold.in.open_mode = OPEN_FLAGS_FCB;
168         io.openold.in.search_attrs = 0;
169         status = smb_raw_open(cli->tree, mem_ctx, &io);
170         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
171         fnum = io.openold.out.fnum;
172
173         smbcli_unlink(cli->tree, fname);
174         CREATE_FILE;
175         smbcli_close(cli->tree, fnum);
176
177         status = smb_raw_open(cli->tree, mem_ctx, &io);
178         CHECK_STATUS(status, NT_STATUS_OK);
179         fnum = io.openold.out.fnum;
180         CHECK_RDWR(fnum, RDWR_RDWR);
181
182         status = smb_raw_open(cli->tree, mem_ctx, &io);
183         CHECK_STATUS(status, NT_STATUS_OK);
184         fnum2 = io.openold.out.fnum;
185         CHECK_RDWR(fnum2, RDWR_RDWR);
186         smbcli_close(cli->tree, fnum2);
187         smbcli_close(cli->tree, fnum);
188
189         /* check the read/write modes */
190         io.openold.level = RAW_OPEN_OPEN;
191         io.openold.in.fname = fname;
192         io.openold.in.search_attrs = 0;
193
194         io.openold.in.open_mode = OPEN_FLAGS_OPEN_READ;
195         status = smb_raw_open(cli->tree, mem_ctx, &io);
196         CHECK_STATUS(status, NT_STATUS_OK);
197         fnum = io.openold.out.fnum;
198         CHECK_RDWR(fnum, RDWR_RDONLY);
199         smbcli_close(cli->tree, fnum);
200
201         io.openold.in.open_mode = OPEN_FLAGS_OPEN_WRITE;
202         status = smb_raw_open(cli->tree, mem_ctx, &io);
203         CHECK_STATUS(status, NT_STATUS_OK);
204         fnum = io.openold.out.fnum;
205         CHECK_RDWR(fnum, RDWR_WRONLY);
206         smbcli_close(cli->tree, fnum);
207
208         io.openold.in.open_mode = OPEN_FLAGS_OPEN_RDWR;
209         status = smb_raw_open(cli->tree, mem_ctx, &io);
210         CHECK_STATUS(status, NT_STATUS_OK);
211         fnum = io.openold.out.fnum;
212         CHECK_RDWR(fnum, RDWR_RDWR);
213         smbcli_close(cli->tree, fnum);
214
215         /* check the share modes roughly - not a complete matrix */
216         io.openold.in.open_mode = OPEN_FLAGS_OPEN_RDWR | OPEN_FLAGS_DENY_WRITE;
217         status = smb_raw_open(cli->tree, mem_ctx, &io);
218         CHECK_STATUS(status, NT_STATUS_OK);
219         fnum = io.openold.out.fnum;
220         CHECK_RDWR(fnum, RDWR_RDWR);
221         
222         if (io.openold.in.open_mode != io.openold.out.rmode) {
223                 printf("(%s) rmode should equal open_mode - 0x%x 0x%x\n",
224                        __location__, io.openold.out.rmode, io.openold.in.open_mode);
225         }
226
227         io.openold.in.open_mode = OPEN_FLAGS_OPEN_RDWR | OPEN_FLAGS_DENY_NONE;
228         status = smb_raw_open(cli->tree, mem_ctx, &io);
229         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
230
231         io.openold.in.open_mode = OPEN_FLAGS_OPEN_READ | OPEN_FLAGS_DENY_NONE;
232         status = smb_raw_open(cli->tree, mem_ctx, &io);
233         CHECK_STATUS(status, NT_STATUS_OK);
234         fnum2 = io.openold.out.fnum;
235         CHECK_RDWR(fnum2, RDWR_RDONLY);
236         smbcli_close(cli->tree, fnum);
237         smbcli_close(cli->tree, fnum2);
238
239
240         /* check the returned write time */
241         io.openold.level = RAW_OPEN_OPEN;
242         io.openold.in.fname = fname;
243         io.openold.in.search_attrs = 0;
244         io.openold.in.open_mode = OPEN_FLAGS_OPEN_READ;
245         status = smb_raw_open(cli->tree, mem_ctx, &io);
246         CHECK_STATUS(status, NT_STATUS_OK);
247         fnum = io.openold.out.fnum;
248
249         /* check other reply fields */
250         CHECK_TIME(io.openold.out.write_time, write_time);
251         CHECK_ALL_INFO(io.openold.out.size, size);
252         CHECK_ALL_INFO(io.openold.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
253
254 done:
255         smbcli_close(cli->tree, fnum);
256         smbcli_unlink(cli->tree, fname);
257
258         return ret;
259 }
260
261
262 /*
263   test RAW_OPEN_OPENX
264 */
265 static BOOL test_openx(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
266 {
267         union smb_open io;
268         union smb_fileinfo finfo;
269         const char *fname = BASEDIR "\\torture_openx.txt";
270         const char *fname_exe = BASEDIR "\\torture_openx.exe";
271         NTSTATUS status;
272         int fnum = -1, fnum2;
273         BOOL ret = True;
274         int i;
275         struct timeval tv;
276         struct {
277                 uint16_t open_func;
278                 BOOL with_file;
279                 NTSTATUS correct_status;
280         } open_funcs[] = {
281                 { OPENX_OPEN_FUNC_OPEN,                           True,  NT_STATUS_OK },
282                 { OPENX_OPEN_FUNC_OPEN,                           False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
283                 { OPENX_OPEN_FUNC_OPEN  | OPENX_OPEN_FUNC_CREATE, True,  NT_STATUS_OK },
284                 { OPENX_OPEN_FUNC_OPEN  | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OK },
285                 { OPENX_OPEN_FUNC_FAIL,                           True,  NT_STATUS_DOS(ERRDOS, ERRbadaccess) },
286                 { OPENX_OPEN_FUNC_FAIL,                           False, NT_STATUS_DOS(ERRDOS, ERRbadaccess) },
287                 { OPENX_OPEN_FUNC_FAIL  | OPENX_OPEN_FUNC_CREATE, True,  NT_STATUS_OBJECT_NAME_COLLISION },
288                 { OPENX_OPEN_FUNC_FAIL  | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OK },
289                 { OPENX_OPEN_FUNC_TRUNC,                          True,  NT_STATUS_OK },
290                 { OPENX_OPEN_FUNC_TRUNC,                          False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
291                 { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, True,  NT_STATUS_OK },
292                 { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OK },
293         };
294
295         printf("Checking RAW_OPEN_OPENX\n");
296         smbcli_unlink(cli->tree, fname);
297
298         io.openx.level = RAW_OPEN_OPENX;
299         io.openx.in.fname = fname;
300         io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
301         io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
302         io.openx.in.search_attrs = 0;
303         io.openx.in.file_attrs = 0;
304         io.openx.in.write_time = 0;
305         io.openx.in.size = 1024*1024;
306         io.openx.in.timeout = 0;
307
308         /* check all combinations of open_func */
309         for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
310                 if (open_funcs[i].with_file) {
311                         fnum = create_complex_file(cli, mem_ctx, fname);
312                         if (fnum == -1) {
313                                 d_printf("Failed to create file %s - %s\n", fname, smbcli_errstr(cli->tree));
314                                 ret = False;
315                                 goto done;
316                         }
317                         smbcli_close(cli->tree, fnum);
318                 }
319                 io.openx.in.open_func = open_funcs[i].open_func;
320                 status = smb_raw_open(cli->tree, mem_ctx, &io);
321                 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
322                         printf("(%s) incorrect status %s should be %s (i=%d with_file=%d open_func=0x%x)\n", 
323                                __location__, nt_errstr(status), nt_errstr(open_funcs[i].correct_status),
324                                i, (int)open_funcs[i].with_file, (int)open_funcs[i].open_func);
325                         ret = False;
326                 }
327                 if (NT_STATUS_IS_OK(status)) {
328                         smbcli_close(cli->tree, io.openx.out.fnum);
329                 }
330                 if (open_funcs[i].with_file) {
331                         smbcli_unlink(cli->tree, fname);
332                 }
333         }
334
335         smbcli_unlink(cli->tree, fname);
336
337         /* check the basic return fields */
338         io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
339         status = smb_raw_open(cli->tree, mem_ctx, &io);
340         CHECK_STATUS(status, NT_STATUS_OK);
341         fnum = io.openx.out.fnum;
342
343         CHECK_ALL_INFO(io.openx.out.size, size);
344         CHECK_TIME(io.openx.out.write_time, write_time);
345         CHECK_ALL_INFO(io.openx.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
346         CHECK_VAL(io.openx.out.access, OPENX_MODE_ACCESS_RDWR);
347         CHECK_VAL(io.openx.out.ftype, 0);
348         CHECK_VAL(io.openx.out.devstate, 0);
349         CHECK_VAL(io.openx.out.action, OPENX_ACTION_CREATED);
350         CHECK_VAL(io.openx.out.size, 1024*1024);
351         CHECK_ALL_INFO(io.openx.in.size, size);
352         smbcli_close(cli->tree, fnum);
353         smbcli_unlink(cli->tree, fname);
354
355         /* check the fields when the file already existed */
356         fnum2 = create_complex_file(cli, mem_ctx, fname);
357         if (fnum2 == -1) {
358                 ret = False;
359                 goto done;
360         }
361         smbcli_close(cli->tree, fnum2);
362
363         io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
364         status = smb_raw_open(cli->tree, mem_ctx, &io);
365         CHECK_STATUS(status, NT_STATUS_OK);
366         fnum = io.openx.out.fnum;
367
368         CHECK_ALL_INFO(io.openx.out.size, size);
369         CHECK_TIME(io.openx.out.write_time, write_time);
370         CHECK_VAL(io.openx.out.action, OPENX_ACTION_EXISTED);
371         CHECK_VAL(io.openx.out.unknown, 0);
372         CHECK_ALL_INFO(io.openx.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
373         smbcli_close(cli->tree, fnum);
374
375         /* now check the search attrib for hidden files - win2003 ignores this? */
376         SET_ATTRIB(FILE_ATTRIBUTE_HIDDEN);
377         CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN, attrib);
378
379         io.openx.in.search_attrs = FILE_ATTRIBUTE_HIDDEN;
380         status = smb_raw_open(cli->tree, mem_ctx, &io);
381         CHECK_STATUS(status, NT_STATUS_OK);
382         smbcli_close(cli->tree, io.openx.out.fnum);
383
384         io.openx.in.search_attrs = 0;
385         status = smb_raw_open(cli->tree, mem_ctx, &io);
386         CHECK_STATUS(status, NT_STATUS_OK);
387         smbcli_close(cli->tree, io.openx.out.fnum);
388
389         SET_ATTRIB(FILE_ATTRIBUTE_NORMAL);
390         smbcli_unlink(cli->tree, fname);
391
392         /* and check attrib on create */
393         io.openx.in.open_func = OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE;
394         io.openx.in.search_attrs = 0;
395         io.openx.in.file_attrs = FILE_ATTRIBUTE_SYSTEM;
396         status = smb_raw_open(cli->tree, mem_ctx, &io);
397         CHECK_STATUS(status, NT_STATUS_OK);
398         CHECK_ALL_INFO(FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE, 
399                        attrib & ~FILE_ATTRIBUTE_NONINDEXED);
400         smbcli_close(cli->tree, io.openx.out.fnum);
401         smbcli_unlink(cli->tree, fname);
402
403         /* check timeout on create - win2003 ignores the timeout! */
404         io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
405         io.openx.in.file_attrs = 0;
406         io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_ALL;
407         status = smb_raw_open(cli->tree, mem_ctx, &io);
408         CHECK_STATUS(status, NT_STATUS_OK);
409         fnum = io.openx.out.fnum;
410
411         io.openx.in.timeout = 20000;
412         tv = timeval_current();
413         io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_NONE;
414         status = smb_raw_open(cli->tree, mem_ctx, &io);
415         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
416         if (timeval_elapsed(&tv) > 3.0) {
417                 printf("(%s) Incorrect timing in openx with timeout - waited %.2f seconds\n",
418                        __location__, timeval_elapsed(&tv));
419                 ret = False;
420         }
421         smbcli_close(cli->tree, fnum);
422         smbcli_unlink(cli->tree, fname);
423
424         /* now this is a really weird one - open for execute implies create?! */
425         io.openx.in.fname = fname;
426         io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
427         io.openx.in.open_mode = OPENX_MODE_ACCESS_EXEC | OPENX_MODE_DENY_NONE;
428         io.openx.in.search_attrs = 0;
429         io.openx.in.open_func = OPENX_OPEN_FUNC_FAIL;
430         io.openx.in.file_attrs = 0;
431         io.openx.in.write_time = 0;
432         io.openx.in.size = 0;
433         io.openx.in.timeout = 0;
434         status = smb_raw_open(cli->tree, mem_ctx, &io);
435         CHECK_STATUS(status, NT_STATUS_OK);
436         smbcli_close(cli->tree, io.openx.out.fnum);
437
438         /* check the extended return flag */
439         io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO | OPENX_FLAGS_EXTENDED_RETURN;
440         io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
441         status = smb_raw_open(cli->tree, mem_ctx, &io);
442         CHECK_STATUS(status, NT_STATUS_OK);
443         CHECK_VAL(io.openx.out.access_mask, SEC_STD_ALL);
444         smbcli_close(cli->tree, io.openx.out.fnum);
445
446         io.openx.in.fname = "\\A.+,;=[].B";
447         status = smb_raw_open(cli->tree, mem_ctx, &io);
448         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
449
450         /* Check the mapping for open exec. */
451
452         /* First create an .exe file. */
453         smbcli_unlink(cli->tree, fname_exe);
454         fnum = create_complex_file(cli, mem_ctx, fname_exe);
455         smbcli_close(cli->tree, fnum);
456
457         io.openx.level = RAW_OPEN_OPENX;
458         io.openx.in.fname = fname_exe;
459         io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
460         io.openx.in.open_mode = OPENX_MODE_ACCESS_EXEC | OPENX_MODE_DENY_NONE;
461         io.openx.in.search_attrs = 0;
462         io.openx.in.file_attrs = 0;
463         io.openx.in.write_time = 0;
464         io.openx.in.size = 0;
465         io.openx.in.timeout = 0;
466         status = smb_raw_open(cli->tree, mem_ctx, &io);
467         CHECK_STATUS(status, NT_STATUS_OK);
468
469         /* Can we read and write ? */
470         CHECK_RDWR(io.openx.out.fnum, RDWR_RDONLY);
471         smbcli_close(cli->tree, io.openx.out.fnum);
472         smbcli_unlink(cli->tree, fname);
473
474 done:
475         smbcli_close(cli->tree, fnum);
476         smbcli_unlink(cli->tree, fname_exe);
477         smbcli_unlink(cli->tree, fname);
478
479         return ret;
480 }
481
482
483 /*
484   test RAW_OPEN_T2OPEN
485
486   many thanks to kukks for a sniff showing how this works with os2->w2k
487 */
488 static BOOL test_t2open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
489 {
490         union smb_open io;
491         union smb_fileinfo finfo;
492         const char *fname1 = BASEDIR "\\torture_t2open_yes.txt";
493         const char *fname2 = BASEDIR "\\torture_t2open_no.txt";
494         const char *fname = BASEDIR "\\torture_t2open_3.txt";
495         NTSTATUS status;
496         int fnum;
497         BOOL ret = True;
498         int i;
499         struct {
500                 uint16_t open_func;
501                 BOOL with_file;
502                 NTSTATUS correct_status;
503         } open_funcs[] = {
504                 { OPENX_OPEN_FUNC_OPEN,                           True,  NT_STATUS_OK },
505                 { OPENX_OPEN_FUNC_OPEN,                           False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
506                 { OPENX_OPEN_FUNC_OPEN  | OPENX_OPEN_FUNC_CREATE, True,  NT_STATUS_OK },
507                 { OPENX_OPEN_FUNC_OPEN  | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OK },
508                 { OPENX_OPEN_FUNC_FAIL,                           True,  NT_STATUS_OBJECT_NAME_COLLISION },
509                 { OPENX_OPEN_FUNC_FAIL,                           False, NT_STATUS_OBJECT_NAME_COLLISION },
510                 { OPENX_OPEN_FUNC_FAIL  | OPENX_OPEN_FUNC_CREATE, True,  NT_STATUS_OBJECT_NAME_COLLISION },
511                 { OPENX_OPEN_FUNC_FAIL  | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OBJECT_NAME_COLLISION },
512                 { OPENX_OPEN_FUNC_TRUNC,                          True,  NT_STATUS_OK },
513                 { OPENX_OPEN_FUNC_TRUNC,                          False, NT_STATUS_OK },
514                 { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, True,  NT_STATUS_OK },
515                 { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OK },
516         };
517
518         fnum = create_complex_file(cli, mem_ctx, fname1);
519         if (fnum == -1) {
520                 d_printf("Failed to create file %s - %s\n", fname1, smbcli_errstr(cli->tree));
521                 ret = False;
522                 goto done;
523         }
524         smbcli_close(cli->tree, fnum);
525
526         printf("Checking RAW_OPEN_T2OPEN\n");
527
528         io.t2open.level = RAW_OPEN_T2OPEN;
529         io.t2open.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
530         io.t2open.in.open_mode = OPENX_MODE_DENY_NONE | OPENX_MODE_ACCESS_RDWR;
531         io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
532         io.t2open.in.search_attrs = 0;
533         io.t2open.in.file_attrs = 0;
534         io.t2open.in.write_time = 0;
535         io.t2open.in.size = 0;
536         io.t2open.in.timeout = 0;
537
538         io.t2open.in.num_eas = 3;
539         io.t2open.in.eas = talloc_array(mem_ctx, struct ea_struct, io.t2open.in.num_eas);
540         io.t2open.in.eas[0].flags = 0;
541         io.t2open.in.eas[0].name.s = ".CLASSINFO";
542         io.t2open.in.eas[0].value = data_blob_talloc(mem_ctx, "first value", 11);
543         io.t2open.in.eas[1].flags = 0;
544         io.t2open.in.eas[1].name.s = "EA TWO";
545         io.t2open.in.eas[1].value = data_blob_talloc(mem_ctx, "foo", 3);
546         io.t2open.in.eas[2].flags = 0;
547         io.t2open.in.eas[2].name.s = "X THIRD";
548         io.t2open.in.eas[2].value = data_blob_talloc(mem_ctx, "xy", 2);
549
550         /* check all combinations of open_func */
551         for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
552                 if (open_funcs[i].with_file) {
553                         io.t2open.in.fname = fname1;
554                 } else {
555                         io.t2open.in.fname = fname2;
556                 }
557                 io.t2open.in.open_func = open_funcs[i].open_func;
558                 status = smb_raw_open(cli->tree, mem_ctx, &io);
559                 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
560                         printf("(%s) incorrect status %s should be %s (i=%d with_file=%d open_func=0x%x)\n", 
561                                __location__, nt_errstr(status), nt_errstr(open_funcs[i].correct_status),
562                                i, (int)open_funcs[i].with_file, (int)open_funcs[i].open_func);
563                         ret = False;
564                 }
565                 if (NT_STATUS_IS_OK(status)) {
566                         smbcli_close(cli->tree, io.t2open.out.fnum);
567                 }
568         }
569
570         smbcli_unlink(cli->tree, fname1);
571         smbcli_unlink(cli->tree, fname2);
572
573         /* check the basic return fields */
574         io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
575         io.t2open.in.write_time = 0;
576         io.t2open.in.fname = fname;
577         status = smb_raw_open(cli->tree, mem_ctx, &io);
578         CHECK_STATUS(status, NT_STATUS_OK);
579         fnum = io.t2open.out.fnum;
580
581         CHECK_ALL_INFO(io.t2open.out.size, size);
582 #if 0
583         /* windows appears to leak uninitialised memory here */
584         CHECK_VAL(io.t2open.out.write_time, 0);
585 #endif
586         CHECK_ALL_INFO(io.t2open.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
587         CHECK_VAL(io.t2open.out.access, OPENX_MODE_DENY_NONE | OPENX_MODE_ACCESS_RDWR);
588         CHECK_VAL(io.t2open.out.ftype, 0);
589         CHECK_VAL(io.t2open.out.devstate, 0);
590         CHECK_VAL(io.t2open.out.action, OPENX_ACTION_CREATED);
591         smbcli_close(cli->tree, fnum);
592
593         status = torture_check_ea(cli, fname, ".CLASSINFO", "first value");
594         CHECK_STATUS(status, NT_STATUS_OK);
595         status = torture_check_ea(cli, fname, "EA TWO", "foo");
596         CHECK_STATUS(status, NT_STATUS_OK);
597         status = torture_check_ea(cli, fname, "X THIRD", "xy");
598         CHECK_STATUS(status, NT_STATUS_OK);
599
600         /* now check the search attrib for hidden files - win2003 ignores this? */
601         SET_ATTRIB(FILE_ATTRIBUTE_HIDDEN);
602         CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN, attrib);
603
604         status = smb_raw_open(cli->tree, mem_ctx, &io);
605         CHECK_STATUS(status, NT_STATUS_OK);
606         smbcli_close(cli->tree, io.t2open.out.fnum);
607
608         status = smb_raw_open(cli->tree, mem_ctx, &io);
609         CHECK_STATUS(status, NT_STATUS_OK);
610         smbcli_close(cli->tree, io.t2open.out.fnum);
611
612         SET_ATTRIB(FILE_ATTRIBUTE_NORMAL);
613         smbcli_unlink(cli->tree, fname);
614
615         /* and check attrib on create */
616         io.t2open.in.open_func = OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE;
617         io.t2open.in.file_attrs = FILE_ATTRIBUTE_SYSTEM;
618         status = smb_raw_open(cli->tree, mem_ctx, &io);
619         CHECK_STATUS(status, NT_STATUS_OK);
620
621         /* check timeout on create - win2003 ignores the timeout! */
622         io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
623         io.t2open.in.file_attrs = 0;
624         io.t2open.in.timeout = 20000;
625         io.t2open.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_ALL;
626         status = smb_raw_open(cli->tree, mem_ctx, &io);
627         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
628
629 done:
630         smbcli_close(cli->tree, fnum);
631         smbcli_unlink(cli->tree, fname);
632
633         return ret;
634 }
635         
636
637 /*
638   test RAW_OPEN_NTCREATEX
639 */
640 static BOOL test_ntcreatex(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
641 {
642         union smb_open io;
643         union smb_fileinfo finfo;
644         const char *fname = BASEDIR "\\torture_ntcreatex.txt";
645         const char *dname = BASEDIR "\\torture_ntcreatex.dir";
646         NTSTATUS status;
647         int fnum = -1;
648         BOOL ret = True;
649         int i;
650         struct {
651                 uint32_t open_disp;
652                 BOOL with_file;
653                 NTSTATUS correct_status;
654         } open_funcs[] = {
655                 { NTCREATEX_DISP_SUPERSEDE,     True,  NT_STATUS_OK },
656                 { NTCREATEX_DISP_SUPERSEDE,     False, NT_STATUS_OK },
657                 { NTCREATEX_DISP_OPEN,          True,  NT_STATUS_OK },
658                 { NTCREATEX_DISP_OPEN,          False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
659                 { NTCREATEX_DISP_CREATE,        True,  NT_STATUS_OBJECT_NAME_COLLISION },
660                 { NTCREATEX_DISP_CREATE,        False, NT_STATUS_OK },
661                 { NTCREATEX_DISP_OPEN_IF,       True,  NT_STATUS_OK },
662                 { NTCREATEX_DISP_OPEN_IF,       False, NT_STATUS_OK },
663                 { NTCREATEX_DISP_OVERWRITE,     True,  NT_STATUS_OK },
664                 { NTCREATEX_DISP_OVERWRITE,     False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
665                 { NTCREATEX_DISP_OVERWRITE_IF,  True,  NT_STATUS_OK },
666                 { NTCREATEX_DISP_OVERWRITE_IF,  False, NT_STATUS_OK },
667                 { 6,                            True,  NT_STATUS_INVALID_PARAMETER },
668                 { 6,                            False, NT_STATUS_INVALID_PARAMETER },
669         };
670
671         printf("Checking RAW_OPEN_NTCREATEX\n");
672
673         /* reasonable default parameters */
674         io.generic.level = RAW_OPEN_NTCREATEX;
675         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
676         io.ntcreatex.in.root_fid = 0;
677         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
678         io.ntcreatex.in.alloc_size = 1024*1024;
679         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
680         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
681         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
682         io.ntcreatex.in.create_options = 0;
683         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
684         io.ntcreatex.in.security_flags = 0;
685         io.ntcreatex.in.fname = fname;
686
687         /* test the open disposition */
688         for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
689                 if (open_funcs[i].with_file) {
690                         fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR|O_TRUNC, DENY_NONE);
691                         if (fnum == -1) {
692                                 d_printf("Failed to create file %s - %s\n", fname, smbcli_errstr(cli->tree));
693                                 ret = False;
694                                 goto done;
695                         }
696                         smbcli_close(cli->tree, fnum);
697                 }
698                 io.ntcreatex.in.open_disposition = open_funcs[i].open_disp;
699                 status = smb_raw_open(cli->tree, mem_ctx, &io);
700                 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
701                         printf("(%s) incorrect status %s should be %s (i=%d with_file=%d open_disp=%d)\n", 
702                                __location__, nt_errstr(status), nt_errstr(open_funcs[i].correct_status),
703                                i, (int)open_funcs[i].with_file, (int)open_funcs[i].open_disp);
704                         ret = False;
705                 }
706                 if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
707                         smbcli_close(cli->tree, io.ntcreatex.out.fnum);
708                         smbcli_unlink(cli->tree, fname);
709                 }
710         }
711
712         /* basic field testing */
713         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
714
715         status = smb_raw_open(cli->tree, mem_ctx, &io);
716         CHECK_STATUS(status, NT_STATUS_OK);
717         fnum = io.ntcreatex.out.fnum;
718
719         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
720         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
721         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
722         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
723         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
724         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
725         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
726         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
727         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
728         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
729         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
730
731         /* check fields when the file already existed */
732         smbcli_close(cli->tree, fnum);
733         smbcli_unlink(cli->tree, fname);
734         fnum = create_complex_file(cli, mem_ctx, fname);
735         if (fnum == -1) {
736                 ret = False;
737                 goto done;
738         }
739         smbcli_close(cli->tree, fnum);
740
741         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
742         status = smb_raw_open(cli->tree, mem_ctx, &io);
743         CHECK_STATUS(status, NT_STATUS_OK);
744         fnum = io.ntcreatex.out.fnum;
745
746         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
747         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
748         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
749         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
750         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
751         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
752         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
753         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
754         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
755         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
756         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
757         smbcli_close(cli->tree, fnum);
758         smbcli_unlink(cli->tree, fname);
759
760
761         /* create a directory */
762         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
763         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
764         io.ntcreatex.in.alloc_size = 0;
765         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
766         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
767         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
768         io.ntcreatex.in.create_options = 0;
769         io.ntcreatex.in.fname = dname;
770         fname = dname;
771
772         smbcli_rmdir(cli->tree, fname);
773         smbcli_unlink(cli->tree, fname);
774
775         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
776         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
777         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
778         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
779         status = smb_raw_open(cli->tree, mem_ctx, &io);
780         CHECK_STATUS(status, NT_STATUS_OK);
781         fnum = io.ntcreatex.out.fnum;
782
783         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
784         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
785         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
786         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
787         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
788         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
789         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
790         CHECK_VAL(io.ntcreatex.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED, 
791                   FILE_ATTRIBUTE_DIRECTORY);
792         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
793         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
794         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
795         CHECK_VAL(io.ntcreatex.out.is_directory, 1);
796         CHECK_VAL(io.ntcreatex.out.size, 0);
797         CHECK_VAL(io.ntcreatex.out.alloc_size, 0);
798         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
799         smbcli_unlink(cli->tree, fname);
800         
801
802 done:
803         smbcli_close(cli->tree, fnum);
804         smbcli_unlink(cli->tree, fname);
805
806         return ret;
807 }
808
809
810 /*
811   test RAW_OPEN_NTTRANS_CREATE
812 */
813 static BOOL test_nttrans_create(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
814 {
815         union smb_open io;
816         union smb_fileinfo finfo;
817         const char *fname = BASEDIR "\\torture_ntcreatex.txt";
818         const char *dname = BASEDIR "\\torture_ntcreatex.dir";
819         NTSTATUS status;
820         int fnum = -1;
821         BOOL ret = True;
822         int i;
823         struct {
824                 uint32_t open_disp;
825                 BOOL with_file;
826                 NTSTATUS correct_status;
827         } open_funcs[] = {
828                 { NTCREATEX_DISP_SUPERSEDE,     True,  NT_STATUS_OK },
829                 { NTCREATEX_DISP_SUPERSEDE,     False, NT_STATUS_OK },
830                 { NTCREATEX_DISP_OPEN,          True,  NT_STATUS_OK },
831                 { NTCREATEX_DISP_OPEN,          False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
832                 { NTCREATEX_DISP_CREATE,        True,  NT_STATUS_OBJECT_NAME_COLLISION },
833                 { NTCREATEX_DISP_CREATE,        False, NT_STATUS_OK },
834                 { NTCREATEX_DISP_OPEN_IF,       True,  NT_STATUS_OK },
835                 { NTCREATEX_DISP_OPEN_IF,       False, NT_STATUS_OK },
836                 { NTCREATEX_DISP_OVERWRITE,     True,  NT_STATUS_OK },
837                 { NTCREATEX_DISP_OVERWRITE,     False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
838                 { NTCREATEX_DISP_OVERWRITE_IF,  True,  NT_STATUS_OK },
839                 { NTCREATEX_DISP_OVERWRITE_IF,  False, NT_STATUS_OK },
840                 { 6,                            True,  NT_STATUS_INVALID_PARAMETER },
841                 { 6,                            False, NT_STATUS_INVALID_PARAMETER },
842         };
843
844         printf("Checking RAW_OPEN_NTTRANS_CREATE\n");
845
846         /* reasonable default parameters */
847         io.generic.level = RAW_OPEN_NTTRANS_CREATE;
848         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
849         io.ntcreatex.in.root_fid = 0;
850         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
851         io.ntcreatex.in.alloc_size = 1024*1024;
852         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
853         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
854         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
855         io.ntcreatex.in.create_options = 0;
856         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
857         io.ntcreatex.in.security_flags = 0;
858         io.ntcreatex.in.fname = fname;
859         io.ntcreatex.in.sec_desc = NULL;
860         io.ntcreatex.in.ea_list = NULL;
861
862         /* test the open disposition */
863         for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
864                 if (open_funcs[i].with_file) {
865                         fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR|O_TRUNC, DENY_NONE);
866                         if (fnum == -1) {
867                                 d_printf("Failed to create file %s - %s\n", fname, smbcli_errstr(cli->tree));
868                                 ret = False;
869                                 goto done;
870                         }
871                         smbcli_close(cli->tree, fnum);
872                 }
873                 io.ntcreatex.in.open_disposition = open_funcs[i].open_disp;
874                 status = smb_raw_open(cli->tree, mem_ctx, &io);
875                 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
876                         printf("(%s) incorrect status %s should be %s (i=%d with_file=%d open_disp=%d)\n", 
877                                __location__, nt_errstr(status), nt_errstr(open_funcs[i].correct_status),
878                                i, (int)open_funcs[i].with_file, (int)open_funcs[i].open_disp);
879                         ret = False;
880                 }
881                 if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
882                         smbcli_close(cli->tree, io.ntcreatex.out.fnum);
883                         smbcli_unlink(cli->tree, fname);
884                 }
885         }
886
887         /* basic field testing */
888         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
889
890         status = smb_raw_open(cli->tree, mem_ctx, &io);
891         CHECK_STATUS(status, NT_STATUS_OK);
892         fnum = io.ntcreatex.out.fnum;
893
894         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
895         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
896         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
897         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
898         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
899         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
900         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
901         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
902         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
903         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
904         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
905
906         /* check fields when the file already existed */
907         smbcli_close(cli->tree, fnum);
908         smbcli_unlink(cli->tree, fname);
909         fnum = create_complex_file(cli, mem_ctx, fname);
910         if (fnum == -1) {
911                 ret = False;
912                 goto done;
913         }
914         smbcli_close(cli->tree, fnum);
915
916         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
917         status = smb_raw_open(cli->tree, mem_ctx, &io);
918         CHECK_STATUS(status, NT_STATUS_OK);
919         fnum = io.ntcreatex.out.fnum;
920
921         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
922         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
923         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
924         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
925         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
926         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
927         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
928         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
929         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
930         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
931         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
932         smbcli_close(cli->tree, fnum);
933         smbcli_unlink(cli->tree, fname);
934
935
936         /* create a directory */
937         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
938         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
939         io.ntcreatex.in.alloc_size = 0;
940         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
941         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
942         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
943         io.ntcreatex.in.create_options = 0;
944         io.ntcreatex.in.fname = dname;
945         fname = dname;
946
947         smbcli_rmdir(cli->tree, fname);
948         smbcli_unlink(cli->tree, fname);
949
950         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
951         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
952         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
953         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
954         status = smb_raw_open(cli->tree, mem_ctx, &io);
955         CHECK_STATUS(status, NT_STATUS_OK);
956         fnum = io.ntcreatex.out.fnum;
957
958         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
959         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
960         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
961         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
962         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
963         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
964         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
965         CHECK_VAL(io.ntcreatex.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED, 
966                   FILE_ATTRIBUTE_DIRECTORY);
967         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
968         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
969         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
970         CHECK_VAL(io.ntcreatex.out.is_directory, 1);
971         CHECK_VAL(io.ntcreatex.out.size, 0);
972         CHECK_VAL(io.ntcreatex.out.alloc_size, 0);
973         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
974         smbcli_unlink(cli->tree, fname);
975         
976
977 done:
978         smbcli_close(cli->tree, fnum);
979         smbcli_unlink(cli->tree, fname);
980
981         return ret;
982 }
983
984 /*
985   test RAW_OPEN_NTCREATEX with an already opened and byte range locked file
986
987   I've got an application that does a similar sequence of ntcreate&x,
988   locking&x and another ntcreate&x with
989   open_disposition==NTCREATEX_DISP_OVERWRITE_IF. Windows 2003 allows the
990   second open.
991 */
992 static BOOL test_ntcreatex_brlocked(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
993 {
994         union smb_open io, io1;
995         union smb_lock io2;
996         struct smb_lock_entry lock[1];
997         const char *fname = BASEDIR "\\torture_ntcreatex.txt";
998         NTSTATUS status;
999         BOOL ret = True;
1000
1001         printf("Testing ntcreatex with a byte range locked file\n");
1002
1003         io.generic.level = RAW_OPEN_NTCREATEX;
1004         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1005         io.ntcreatex.in.root_fid = 0;
1006         io.ntcreatex.in.access_mask = 0x2019f;
1007         io.ntcreatex.in.alloc_size = 0;
1008         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1009         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1010                 NTCREATEX_SHARE_ACCESS_WRITE;
1011         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1012         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
1013         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
1014         io.ntcreatex.in.security_flags = NTCREATEX_SECURITY_DYNAMIC |
1015                 NTCREATEX_SECURITY_ALL;
1016         io.ntcreatex.in.fname = fname;
1017
1018         status = smb_raw_open(cli->tree, mem_ctx, &io);
1019         CHECK_STATUS(status, NT_STATUS_OK);
1020
1021         io2.lockx.level = RAW_LOCK_LOCKX;
1022         io2.lockx.in.fnum = io.ntcreatex.out.fnum;
1023         io2.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1024         io2.lockx.in.timeout = 0;
1025         io2.lockx.in.ulock_cnt = 0;
1026         io2.lockx.in.lock_cnt = 1;
1027         lock[0].pid = cli->session->pid;
1028         lock[0].offset = 0;
1029         lock[0].count = 0x1;
1030         io2.lockx.in.locks = &lock[0];
1031         status = smb_raw_lock(cli->tree, &io2);
1032         CHECK_STATUS(status, NT_STATUS_OK);
1033
1034         io1.generic.level = RAW_OPEN_NTCREATEX;
1035         io1.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1036         io1.ntcreatex.in.root_fid = 0;
1037         io1.ntcreatex.in.access_mask = 0x20196;
1038         io1.ntcreatex.in.alloc_size = 0;
1039         io1.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1040         io1.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1041                 NTCREATEX_SHARE_ACCESS_WRITE;
1042         io1.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1043         io1.ntcreatex.in.create_options = 0;
1044         io1.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
1045         io1.ntcreatex.in.security_flags = NTCREATEX_SECURITY_DYNAMIC |
1046                 NTCREATEX_SECURITY_ALL;
1047         io1.ntcreatex.in.fname = fname;
1048
1049         status = smb_raw_open(cli->tree, mem_ctx, &io1);
1050         CHECK_STATUS(status, NT_STATUS_OK);
1051
1052  done:
1053         smbcli_close(cli->tree, io.ntcreatex.out.fnum);
1054         smbcli_close(cli->tree, io1.ntcreatex.out.fnum);
1055         smbcli_unlink(cli->tree, fname);
1056         return ret;
1057 }
1058
1059 /*
1060   test RAW_OPEN_MKNEW
1061 */
1062 static BOOL test_mknew(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
1063 {
1064         union smb_open io;
1065         const char *fname = BASEDIR "\\torture_mknew.txt";
1066         NTSTATUS status;
1067         int fnum = -1;
1068         BOOL ret = True;
1069         time_t basetime = (time(NULL) + 3600*24*3) & ~1;
1070         union smb_fileinfo finfo;
1071
1072         printf("Checking RAW_OPEN_MKNEW\n");
1073
1074         io.mknew.level = RAW_OPEN_MKNEW;
1075         io.mknew.in.attrib = 0;
1076         io.mknew.in.write_time = 0;
1077         io.mknew.in.fname = fname;
1078         status = smb_raw_open(cli->tree, mem_ctx, &io);
1079         CHECK_STATUS(status, NT_STATUS_OK);
1080         fnum = io.mknew.out.fnum;
1081
1082         status = smb_raw_open(cli->tree, mem_ctx, &io);
1083         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
1084
1085         smbcli_close(cli->tree, fnum);
1086         smbcli_unlink(cli->tree, fname);
1087
1088         /* make sure write_time works */
1089         io.mknew.in.write_time = basetime;
1090         status = smb_raw_open(cli->tree, mem_ctx, &io);
1091         CHECK_STATUS(status, NT_STATUS_OK);
1092         fnum = io.mknew.out.fnum;
1093         CHECK_TIME(basetime, write_time);
1094
1095         smbcli_close(cli->tree, fnum);
1096         smbcli_unlink(cli->tree, fname);
1097
1098         /* make sure file_attrs works */
1099         io.mknew.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1100         status = smb_raw_open(cli->tree, mem_ctx, &io);
1101         CHECK_STATUS(status, NT_STATUS_OK);
1102         fnum = io.mknew.out.fnum;
1103         CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE, 
1104                        attrib & ~FILE_ATTRIBUTE_NONINDEXED);
1105         
1106 done:
1107         smbcli_close(cli->tree, fnum);
1108         smbcli_unlink(cli->tree, fname);
1109
1110         return ret;
1111 }
1112
1113
1114 /*
1115   test RAW_OPEN_CREATE
1116 */
1117 static BOOL test_create(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
1118 {
1119         union smb_open io;
1120         const char *fname = BASEDIR "\\torture_create.txt";
1121         NTSTATUS status;
1122         int fnum = -1;
1123         BOOL ret = True;
1124         time_t basetime = (time(NULL) + 3600*24*3) & ~1;
1125         union smb_fileinfo finfo;
1126
1127         printf("Checking RAW_OPEN_CREATE\n");
1128
1129         io.create.level = RAW_OPEN_CREATE;
1130         io.create.in.attrib = 0;
1131         io.create.in.write_time = 0;
1132         io.create.in.fname = fname;
1133         status = smb_raw_open(cli->tree, mem_ctx, &io);
1134         CHECK_STATUS(status, NT_STATUS_OK);
1135         fnum = io.create.out.fnum;
1136
1137         status = smb_raw_open(cli->tree, mem_ctx, &io);
1138         CHECK_STATUS(status, NT_STATUS_OK);
1139
1140         smbcli_close(cli->tree, io.create.out.fnum);
1141         smbcli_close(cli->tree, fnum);
1142         smbcli_unlink(cli->tree, fname);
1143
1144         /* make sure write_time works */
1145         io.create.in.write_time = basetime;
1146         status = smb_raw_open(cli->tree, mem_ctx, &io);
1147         CHECK_STATUS(status, NT_STATUS_OK);
1148         fnum = io.create.out.fnum;
1149         CHECK_TIME(basetime, write_time);
1150
1151         smbcli_close(cli->tree, fnum);
1152         smbcli_unlink(cli->tree, fname);
1153
1154         /* make sure file_attrs works */
1155         io.create.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1156         status = smb_raw_open(cli->tree, mem_ctx, &io);
1157         CHECK_STATUS(status, NT_STATUS_OK);
1158         fnum = io.create.out.fnum;
1159         CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE, 
1160                        attrib & ~FILE_ATTRIBUTE_NONINDEXED);
1161         
1162 done:
1163         smbcli_close(cli->tree, fnum);
1164         smbcli_unlink(cli->tree, fname);
1165
1166         return ret;
1167 }
1168
1169
1170 /*
1171   test RAW_OPEN_CTEMP
1172 */
1173 static BOOL test_ctemp(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
1174 {
1175         union smb_open io;
1176         NTSTATUS status;
1177         int fnum = -1;
1178         BOOL ret = True;
1179         time_t basetime = (time(NULL) + 3600*24*3) & ~1;
1180         union smb_fileinfo finfo;
1181         const char *name, *fname = NULL;
1182
1183         printf("Checking RAW_OPEN_CTEMP\n");
1184
1185         io.ctemp.level = RAW_OPEN_CTEMP;
1186         io.ctemp.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1187         io.ctemp.in.write_time = basetime;
1188         io.ctemp.in.directory = BASEDIR;
1189         status = smb_raw_open(cli->tree, mem_ctx, &io);
1190         CHECK_STATUS(status, NT_STATUS_OK);
1191         fnum = io.ctemp.out.fnum;
1192
1193         name = io.ctemp.out.name;
1194
1195         finfo.generic.level = RAW_FILEINFO_NAME_INFO;
1196         finfo.generic.in.fnum = fnum;
1197         status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo);
1198         CHECK_STATUS(status, NT_STATUS_OK);
1199
1200         fname = finfo.name_info.out.fname.s;
1201         d_printf("ctemp name=%s  real name=%s\n", name, fname);
1202
1203 done:
1204         smbcli_close(cli->tree, fnum);
1205         if (fname) {
1206                 smbcli_unlink(cli->tree, fname);
1207         }
1208
1209         return ret;
1210 }
1211
1212
1213 /*
1214   test chained RAW_OPEN_OPENX_READX
1215 */
1216 static BOOL test_chained(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
1217 {
1218         union smb_open io;
1219         const char *fname = BASEDIR "\\torture_chained.txt";
1220         NTSTATUS status;
1221         int fnum = -1;
1222         BOOL ret = True;
1223         const char *buf = "test";
1224         char buf2[4];
1225
1226         printf("Checking RAW_OPEN_OPENX chained with READX\n");
1227         smbcli_unlink(cli->tree, fname);
1228
1229         fnum = create_complex_file(cli, mem_ctx, fname);
1230
1231         smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
1232
1233         smbcli_close(cli->tree, fnum);  
1234
1235         io.openxreadx.level = RAW_OPEN_OPENX_READX;
1236         io.openxreadx.in.fname = fname;
1237         io.openxreadx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
1238         io.openxreadx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
1239         io.openxreadx.in.open_func = OPENX_OPEN_FUNC_OPEN;
1240         io.openxreadx.in.search_attrs = 0;
1241         io.openxreadx.in.file_attrs = 0;
1242         io.openxreadx.in.write_time = 0;
1243         io.openxreadx.in.size = 1024*1024;
1244         io.openxreadx.in.timeout = 0;
1245         
1246         io.openxreadx.in.offset = 0;
1247         io.openxreadx.in.mincnt = sizeof(buf);
1248         io.openxreadx.in.maxcnt = sizeof(buf);
1249         io.openxreadx.in.remaining = 0;
1250         io.openxreadx.out.data = (uint8_t *)buf2;
1251
1252         status = smb_raw_open(cli->tree, mem_ctx, &io);
1253         CHECK_STATUS(status, NT_STATUS_OK);
1254         fnum = io.openxreadx.out.fnum;
1255
1256         if (memcmp(buf, buf2, sizeof(buf)) != 0) {
1257                 d_printf("wrong data in reply buffer\n");
1258                 ret = False;
1259         }
1260
1261 done:
1262         smbcli_close(cli->tree, fnum);
1263         smbcli_unlink(cli->tree, fname);
1264
1265         return ret;
1266 }
1267
1268 /* A little torture test to expose a race condition in Samba 3.0.20 ... :-) */
1269
1270 static BOOL test_raw_open_multi(void)
1271 {
1272         struct smbcli_state *cli;
1273         TALLOC_CTX *mem_ctx = talloc_init("torture_test_oplock_multi");
1274         const char *fname = "\\test_oplock.dat";
1275         NTSTATUS status;
1276         BOOL ret = True;
1277         union smb_open io;
1278         struct smbcli_state **clients;
1279         struct smbcli_request **requests;
1280         union smb_open *ios;
1281         const char *host = lp_parm_string(-1, "torture", "host");
1282         const char *share = lp_parm_string(-1, "torture", "share");
1283         int i, num_files = 3;
1284         struct event_context *ev;
1285         int num_ok = 0;
1286         int num_collision = 0;
1287         
1288         ev = event_context_init(mem_ctx);
1289         clients = talloc_array(mem_ctx, struct smbcli_state *, num_files);
1290         requests = talloc_array(mem_ctx, struct smbcli_request *, num_files);
1291         ios = talloc_array(mem_ctx, union smb_open, num_files);
1292         if ((ev == NULL) || (clients == NULL) || (requests == NULL) ||
1293             (ios == NULL)) {
1294                 DEBUG(0, ("talloc failed\n"));
1295                 return False;
1296         }
1297
1298         if (!torture_open_connection_share(mem_ctx, &cli, host, share, ev)) {
1299                 return False;
1300         }
1301
1302         cli->tree->session->transport->options.request_timeout = 60000;
1303
1304         for (i=0; i<num_files; i++) {
1305                 if (!torture_open_connection_share(mem_ctx, &(clients[i]),
1306                                                    host, share, ev)) {
1307                         DEBUG(0, ("Could not open %d'th connection\n", i));
1308                         return False;
1309                 }
1310                 clients[i]->tree->session->transport->
1311                         options.request_timeout = 60000;
1312         }
1313
1314         /* cleanup */
1315         smbcli_unlink(cli->tree, fname);
1316
1317         /*
1318           base ntcreatex parms
1319         */
1320         io.generic.level = RAW_OPEN_NTCREATEX;
1321         io.ntcreatex.in.root_fid = 0;
1322         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1323         io.ntcreatex.in.alloc_size = 0;
1324         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1325         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1326                 NTCREATEX_SHARE_ACCESS_WRITE|
1327                 NTCREATEX_SHARE_ACCESS_DELETE;
1328         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1329         io.ntcreatex.in.create_options = 0;
1330         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1331         io.ntcreatex.in.security_flags = 0;
1332         io.ntcreatex.in.fname = fname;
1333         io.ntcreatex.in.flags = 0;
1334
1335         for (i=0; i<num_files; i++) {
1336                 ios[i] = io;
1337                 requests[i] = smb_raw_open_send(clients[i]->tree, &ios[i]);
1338                 if (requests[i] == NULL) {
1339                         DEBUG(0, ("could not send %d'th request\n", i));
1340                         return False;
1341                 }
1342         }
1343
1344         DEBUG(10, ("waiting for replies\n"));
1345         while (1) {
1346                 BOOL unreplied = False;
1347                 for (i=0; i<num_files; i++) {
1348                         if (requests[i] == NULL) {
1349                                 continue;
1350                         }
1351                         if (requests[i]->state < SMBCLI_REQUEST_DONE) {
1352                                 unreplied = True;
1353                                 break;
1354                         }
1355                         status = smb_raw_open_recv(requests[i], mem_ctx,
1356                                                    &ios[i]);
1357
1358                         DEBUG(0, ("File %d returned status %s\n", i,
1359                                   nt_errstr(status)));
1360
1361                         if (NT_STATUS_IS_OK(status)) {
1362                                 num_ok += 1;
1363                         } 
1364
1365                         if (NT_STATUS_EQUAL(status,
1366                                             NT_STATUS_OBJECT_NAME_COLLISION)) {
1367                                 num_collision += 1;
1368                         }
1369
1370                         requests[i] = NULL;
1371                 }
1372                 if (!unreplied) {
1373                         break;
1374                 }
1375
1376                 if (event_loop_once(ev) != 0) {
1377                         DEBUG(0, ("event_loop_once failed\n"));
1378                         return False;
1379                 }
1380         }
1381
1382         if ((num_ok != 1) || (num_ok + num_collision != num_files)) {
1383                 ret = False;
1384         }
1385
1386         for (i=0; i<num_files; i++) {
1387                 torture_close_connection(clients[i]);
1388         }
1389         talloc_free(mem_ctx);
1390         return ret;
1391 }
1392
1393 /* basic testing of all RAW_OPEN_* calls 
1394 */
1395 BOOL torture_raw_open(void)
1396 {
1397         struct smbcli_state *cli;
1398         BOOL ret = True;
1399         TALLOC_CTX *mem_ctx;
1400
1401         if (!torture_open_connection(&cli)) {
1402                 return False;
1403         }
1404
1405         mem_ctx = talloc_init("torture_raw_open");
1406
1407         if (!torture_setup_dir(cli, BASEDIR)) {
1408                 return False;
1409         }
1410
1411         ret &= test_ntcreatex_brlocked(cli, mem_ctx);
1412         ret &= test_open(cli, mem_ctx);
1413         ret &= test_raw_open_multi();
1414         ret &= test_openx(cli, mem_ctx);
1415         ret &= test_ntcreatex(cli, mem_ctx);
1416         ret &= test_nttrans_create(cli, mem_ctx);
1417         ret &= test_t2open(cli, mem_ctx);
1418         ret &= test_mknew(cli, mem_ctx);
1419         ret &= test_create(cli, mem_ctx);
1420         ret &= test_ctemp(cli, mem_ctx);
1421         ret &= test_chained(cli, mem_ctx);
1422
1423         smb_raw_exit(cli->session);
1424         smbcli_deltree(cli->tree, BASEDIR);
1425
1426         torture_close_connection(cli);
1427         talloc_free(mem_ctx);
1428         return ret;
1429 }