r4063: - change char * -> uint8_t in struct request_buffer
[sfrench/samba-autobuild/.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 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 "libcli/raw/libcliraw.h"
23 #include "system/time.h"
24 #include "librpc/gen_ndr/ndr_security.h"
25
26 /* enum for whether reads/writes are possible on a file */
27 enum rdwr_mode {RDWR_NONE, RDWR_RDONLY, RDWR_WRONLY, RDWR_RDWR};
28
29 #define BASEDIR "\\rawopen"
30
31 /*
32   check if a open file can be read/written
33 */
34 static enum rdwr_mode check_rdwr(struct smbcli_tree *tree, int fnum)
35 {
36         uint8_t c = 1;
37         BOOL can_read  = (smbcli_read(tree, fnum, &c, 0, 1) == 1);
38         BOOL can_write = (smbcli_write(tree, fnum, 0, &c, 0, 1) == 1);
39         if ( can_read &&  can_write) return RDWR_RDWR;
40         if ( can_read && !can_write) return RDWR_RDONLY;
41         if (!can_read &&  can_write) return RDWR_WRONLY;
42         return RDWR_NONE;
43 }
44
45 /*
46   describe a RDWR mode as a string
47 */
48 static const char *rdwr_string(enum rdwr_mode m)
49 {
50         switch (m) {
51         case RDWR_NONE: return "NONE";
52         case RDWR_RDONLY: return "RDONLY";
53         case RDWR_WRONLY: return "WRONLY";
54         case RDWR_RDWR: return "RDWR";
55         }
56         return "-";
57 }
58
59 #define CHECK_STATUS(status, correct) do { \
60         if (!NT_STATUS_EQUAL(status, correct)) { \
61                 printf("(%s) Incorrect status %s - should be %s\n", \
62                        __location__, nt_errstr(status), nt_errstr(correct)); \
63                 ret = False; \
64                 goto done; \
65         }} while (0)
66
67 #define CREATE_FILE do { \
68         fnum = create_complex_file(cli, mem_ctx, fname); \
69         if (fnum == -1) { \
70                 printf("(%s) Failed to create %s - %s\n", __location__, fname, smbcli_errstr(cli->tree)); \
71                 ret = False; \
72                 goto done; \
73         }} while (0)
74
75 #define CHECK_RDWR(fnum, correct) do { \
76         enum rdwr_mode m = check_rdwr(cli->tree, fnum); \
77         if (m != correct) { \
78                 printf("(%s) Incorrect readwrite mode %s - expected %s\n", \
79                        __location__, rdwr_string(m), rdwr_string(correct)); \
80                 ret = False; \
81         }} while (0)
82
83 #define CHECK_TIME(t, field) do { \
84         time_t t1, t2; \
85         finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
86         finfo.all_info.in.fname = fname; \
87         status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo); \
88         CHECK_STATUS(status, NT_STATUS_OK); \
89         t1 = t & ~1; \
90         t2 = nt_time_to_unix(finfo.all_info.out.field) & ~1; \
91         if (ABS(t1-t2) > 2) { \
92                 printf("(%s) wrong time for field %s  %s - %s\n", \
93                        __location__, #field, \
94                        timestring(mem_ctx, t1), \
95                        timestring(mem_ctx, t2)); \
96                 dump_all_info(mem_ctx, &finfo); \
97                 ret = False; \
98         }} while (0)
99
100 #define CHECK_NTTIME(t, field) do { \
101         NTTIME t2; \
102         finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
103         finfo.all_info.in.fname = fname; \
104         status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo); \
105         CHECK_STATUS(status, NT_STATUS_OK); \
106         t2 = finfo.all_info.out.field; \
107         if (t != t2) { \
108                 printf("(%s) wrong time for field %s  %s - %s\n", \
109                        __location__, #field, \
110                        nt_time_string(mem_ctx, t), \
111                        nt_time_string(mem_ctx, t2)); \
112                 dump_all_info(mem_ctx, &finfo); \
113                 ret = False; \
114         }} while (0)
115
116 #define CHECK_ALL_INFO(v, field) do { \
117         finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
118         finfo.all_info.in.fname = fname; \
119         status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo); \
120         CHECK_STATUS(status, NT_STATUS_OK); \
121         if ((v) != (finfo.all_info.out.field)) { \
122                 printf("(%s) wrong value for field %s  0x%x - 0x%x\n", \
123                        __location__, #field, (int)v, (int)(finfo.all_info.out.field)); \
124                 dump_all_info(mem_ctx, &finfo); \
125                 ret = False; \
126         }} while (0)
127
128 #define CHECK_VAL(v, correct) do { \
129         if ((v) != (correct)) { \
130                 printf("(%s) wrong value for %s  0x%x - should be 0x%x\n", \
131                        __location__, #v, (int)(v), (int)correct); \
132                 ret = False; \
133         }} while (0)
134
135 #define SET_ATTRIB(sattrib) do { \
136         union smb_setfileinfo sfinfo; \
137         sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION; \
138         sfinfo.generic.file.fname = fname; \
139         ZERO_STRUCT(sfinfo.basic_info.in); \
140         sfinfo.basic_info.in.attrib = sattrib; \
141         status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
142         if (!NT_STATUS_IS_OK(status)) { \
143                 printf("(%s) Failed to set attrib 0x%x on %s\n", \
144                        __location__, sattrib, fname); \
145         }} while (0)
146
147 /*
148   test RAW_OPEN_OPEN
149 */
150 static BOOL test_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
151 {
152         union smb_open io;
153         union smb_fileinfo finfo;
154         const char *fname = BASEDIR "\\torture_open.txt";
155         NTSTATUS status;
156         int fnum = -1, fnum2;
157         BOOL ret = True;
158
159         printf("Checking RAW_OPEN_OPEN\n");
160
161         io.openold.level = RAW_OPEN_OPEN;
162         io.openold.in.fname = fname;
163         io.openold.in.flags = OPEN_FLAGS_FCB;
164         io.openold.in.search_attrs = 0;
165         status = smb_raw_open(cli->tree, mem_ctx, &io);
166         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
167         fnum = io.openold.out.fnum;
168
169         smbcli_unlink(cli->tree, fname);
170         CREATE_FILE;
171         smbcli_close(cli->tree, fnum);
172
173         status = smb_raw_open(cli->tree, mem_ctx, &io);
174         CHECK_STATUS(status, NT_STATUS_OK);
175         fnum = io.openold.out.fnum;
176         CHECK_RDWR(fnum, RDWR_RDWR);
177
178         status = smb_raw_open(cli->tree, mem_ctx, &io);
179         CHECK_STATUS(status, NT_STATUS_OK);
180         fnum2 = io.openold.out.fnum;
181         CHECK_RDWR(fnum2, RDWR_RDWR);
182         smbcli_close(cli->tree, fnum2);
183         smbcli_close(cli->tree, fnum);
184
185         /* check the read/write modes */
186         io.openold.level = RAW_OPEN_OPEN;
187         io.openold.in.fname = fname;
188         io.openold.in.search_attrs = 0;
189
190         io.openold.in.flags = OPEN_FLAGS_OPEN_READ;
191         status = smb_raw_open(cli->tree, mem_ctx, &io);
192         CHECK_STATUS(status, NT_STATUS_OK);
193         fnum = io.openold.out.fnum;
194         CHECK_RDWR(fnum, RDWR_RDONLY);
195         smbcli_close(cli->tree, fnum);
196
197         io.openold.in.flags = OPEN_FLAGS_OPEN_WRITE;
198         status = smb_raw_open(cli->tree, mem_ctx, &io);
199         CHECK_STATUS(status, NT_STATUS_OK);
200         fnum = io.openold.out.fnum;
201         CHECK_RDWR(fnum, RDWR_WRONLY);
202         smbcli_close(cli->tree, fnum);
203
204         io.openold.in.flags = OPEN_FLAGS_OPEN_RDWR;
205         status = smb_raw_open(cli->tree, mem_ctx, &io);
206         CHECK_STATUS(status, NT_STATUS_OK);
207         fnum = io.openold.out.fnum;
208         CHECK_RDWR(fnum, RDWR_RDWR);
209         smbcli_close(cli->tree, fnum);
210
211         /* check the share modes roughly - not a complete matrix */
212         io.openold.in.flags = OPEN_FLAGS_OPEN_RDWR | OPEN_FLAGS_DENY_WRITE;
213         status = smb_raw_open(cli->tree, mem_ctx, &io);
214         CHECK_STATUS(status, NT_STATUS_OK);
215         fnum = io.openold.out.fnum;
216         CHECK_RDWR(fnum, RDWR_RDWR);
217         
218         if (io.openold.in.flags != io.openold.out.rmode) {
219                 printf("(%s) rmode should equal flags - 0x%x 0x%x\n",
220                        __location__, io.openold.out.rmode, io.openold.in.flags);
221         }
222
223         io.openold.in.flags = OPEN_FLAGS_OPEN_RDWR | OPEN_FLAGS_DENY_NONE;
224         status = smb_raw_open(cli->tree, mem_ctx, &io);
225         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
226
227         io.openold.in.flags = OPEN_FLAGS_OPEN_READ | OPEN_FLAGS_DENY_NONE;
228         status = smb_raw_open(cli->tree, mem_ctx, &io);
229         CHECK_STATUS(status, NT_STATUS_OK);
230         fnum2 = io.openold.out.fnum;
231         CHECK_RDWR(fnum2, RDWR_RDONLY);
232         smbcli_close(cli->tree, fnum);
233         smbcli_close(cli->tree, fnum2);
234
235
236         /* check the returned write time */
237         io.openold.level = RAW_OPEN_OPEN;
238         io.openold.in.fname = fname;
239         io.openold.in.search_attrs = 0;
240         io.openold.in.flags = OPEN_FLAGS_OPEN_READ;
241         status = smb_raw_open(cli->tree, mem_ctx, &io);
242         CHECK_STATUS(status, NT_STATUS_OK);
243         fnum = io.openold.out.fnum;
244
245         /* check other reply fields */
246         CHECK_TIME(io.openold.out.write_time, write_time);
247         CHECK_ALL_INFO(io.openold.out.size, size);
248         CHECK_ALL_INFO(io.openold.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
249
250 done:
251         smbcli_close(cli->tree, fnum);
252         smbcli_unlink(cli->tree, fname);
253
254         return ret;
255 }
256
257
258 /*
259   test RAW_OPEN_OPENX
260 */
261 static BOOL test_openx(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
262 {
263         union smb_open io;
264         union smb_fileinfo finfo;
265         const char *fname = BASEDIR "\\torture_openx.txt";
266         NTSTATUS status;
267         int fnum = -1, fnum2;
268         BOOL ret = True;
269         int i;
270         struct timeval tv;
271         struct {
272                 uint16_t open_func;
273                 BOOL with_file;
274                 NTSTATUS correct_status;
275         } open_funcs[] = {
276                 { OPENX_OPEN_FUNC_OPEN,                           True,  NT_STATUS_OK },
277                 { OPENX_OPEN_FUNC_OPEN,                           False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
278                 { OPENX_OPEN_FUNC_OPEN  | OPENX_OPEN_FUNC_CREATE, True,  NT_STATUS_OK },
279                 { OPENX_OPEN_FUNC_OPEN  | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OK },
280                 { OPENX_OPEN_FUNC_FAIL,                           True,  NT_STATUS_INVALID_LOCK_SEQUENCE },
281                 { OPENX_OPEN_FUNC_FAIL,                           False, NT_STATUS_INVALID_LOCK_SEQUENCE },
282                 { OPENX_OPEN_FUNC_FAIL  | OPENX_OPEN_FUNC_CREATE, True,  NT_STATUS_OBJECT_NAME_COLLISION },
283                 { OPENX_OPEN_FUNC_FAIL  | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OK },
284                 { OPENX_OPEN_FUNC_TRUNC,                          True,  NT_STATUS_OK },
285                 { OPENX_OPEN_FUNC_TRUNC,                          False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
286                 { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, True,  NT_STATUS_OK },
287                 { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OK },
288         };
289
290         printf("Checking RAW_OPEN_OPENX\n");
291         smbcli_unlink(cli->tree, fname);
292
293         io.openx.level = RAW_OPEN_OPENX;
294         io.openx.in.fname = fname;
295         io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
296         io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
297         io.openx.in.search_attrs = 0;
298         io.openx.in.file_attrs = 0;
299         io.openx.in.write_time = 0;
300         io.openx.in.size = 1024*1024;
301         io.openx.in.timeout = 0;
302
303         /* check all combinations of open_func */
304         for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
305                 if (open_funcs[i].with_file) {
306                         fnum = create_complex_file(cli, mem_ctx, fname);
307                         if (fnum == -1) {
308                                 d_printf("Failed to create file %s - %s\n", fname, smbcli_errstr(cli->tree));
309                                 ret = False;
310                                 goto done;
311                         }
312                         smbcli_close(cli->tree, fnum);
313                 }
314                 io.openx.in.open_func = open_funcs[i].open_func;
315                 status = smb_raw_open(cli->tree, mem_ctx, &io);
316                 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
317                         printf("(%s) incorrect status %s should be %s (i=%d with_file=%d open_func=0x%x)\n", 
318                                __location__, nt_errstr(status), nt_errstr(open_funcs[i].correct_status),
319                                i, (int)open_funcs[i].with_file, (int)open_funcs[i].open_func);
320                         ret = False;
321                 }
322                 if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
323                         smbcli_close(cli->tree, io.openx.out.fnum);
324                         smbcli_unlink(cli->tree, fname);
325                 }
326         }
327
328         /* check the basic return fields */
329         io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
330         status = smb_raw_open(cli->tree, mem_ctx, &io);
331         CHECK_STATUS(status, NT_STATUS_OK);
332         fnum = io.openx.out.fnum;
333
334         CHECK_ALL_INFO(io.openx.out.size, size);
335         CHECK_TIME(io.openx.out.write_time, write_time);
336         CHECK_ALL_INFO(io.openx.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
337         CHECK_VAL(io.openx.out.access, OPENX_MODE_ACCESS_RDWR);
338         CHECK_VAL(io.openx.out.ftype, 0);
339         CHECK_VAL(io.openx.out.devstate, 0);
340         CHECK_VAL(io.openx.out.action, OPENX_ACTION_CREATED);
341         CHECK_VAL(io.openx.out.size, 1024*1024);
342         CHECK_ALL_INFO(io.openx.in.size, size);
343         smbcli_close(cli->tree, fnum);
344         smbcli_unlink(cli->tree, fname);
345
346         /* check the fields when the file already existed */
347         fnum2 = create_complex_file(cli, mem_ctx, fname);
348         if (fnum2 == -1) {
349                 ret = False;
350                 goto done;
351         }
352         smbcli_close(cli->tree, fnum2);
353
354         io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
355         status = smb_raw_open(cli->tree, mem_ctx, &io);
356         CHECK_STATUS(status, NT_STATUS_OK);
357         fnum = io.openx.out.fnum;
358
359         CHECK_ALL_INFO(io.openx.out.size, size);
360         CHECK_TIME(io.openx.out.write_time, write_time);
361         CHECK_VAL(io.openx.out.action, OPENX_ACTION_EXISTED);
362         CHECK_VAL(io.openx.out.unknown, 0);
363         CHECK_ALL_INFO(io.openx.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
364         smbcli_close(cli->tree, fnum);
365
366         /* now check the search attrib for hidden files - win2003 ignores this? */
367         SET_ATTRIB(FILE_ATTRIBUTE_HIDDEN);
368         CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN, attrib);
369
370         io.openx.in.search_attrs = FILE_ATTRIBUTE_HIDDEN;
371         status = smb_raw_open(cli->tree, mem_ctx, &io);
372         CHECK_STATUS(status, NT_STATUS_OK);
373         smbcli_close(cli->tree, io.openx.out.fnum);
374
375         io.openx.in.search_attrs = 0;
376         status = smb_raw_open(cli->tree, mem_ctx, &io);
377         CHECK_STATUS(status, NT_STATUS_OK);
378         smbcli_close(cli->tree, io.openx.out.fnum);
379
380         SET_ATTRIB(FILE_ATTRIBUTE_NORMAL);
381         smbcli_unlink(cli->tree, fname);
382
383         /* and check attrib on create */
384         io.openx.in.open_func = OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE;
385         io.openx.in.search_attrs = 0;
386         io.openx.in.file_attrs = FILE_ATTRIBUTE_SYSTEM;
387         status = smb_raw_open(cli->tree, mem_ctx, &io);
388         CHECK_STATUS(status, NT_STATUS_OK);
389         CHECK_ALL_INFO(FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE, 
390                        attrib & ~FILE_ATTRIBUTE_NONINDEXED);
391         smbcli_close(cli->tree, io.openx.out.fnum);
392         smbcli_unlink(cli->tree, fname);
393
394         /* check timeout on create - win2003 ignores the timeout! */
395         io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
396         io.openx.in.file_attrs = 0;
397         io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_ALL;
398         status = smb_raw_open(cli->tree, mem_ctx, &io);
399         CHECK_STATUS(status, NT_STATUS_OK);
400         fnum = io.openx.out.fnum;
401
402         io.openx.in.timeout = 20000;
403         tv = timeval_current();
404         io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_NONE;
405         status = smb_raw_open(cli->tree, mem_ctx, &io);
406         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
407         if (timeval_elapsed(&tv) > 3.0) {
408                 printf("(%s) Incorrect timing in openx with timeout - waited %.2f seconds\n",
409                        __location__, timeval_elapsed(&tv));
410                 ret = False;
411         }
412         smbcli_close(cli->tree, fnum);
413         smbcli_unlink(cli->tree, fname);
414
415         /* now this is a really weird one - open for execute implies create?! */
416         io.openx.in.fname = fname;
417         io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
418         io.openx.in.open_mode = OPENX_MODE_ACCESS_EXEC | OPENX_MODE_DENY_NONE;
419         io.openx.in.search_attrs = 0;
420         io.openx.in.open_func = OPENX_OPEN_FUNC_FAIL;
421         io.openx.in.file_attrs = 0;
422         io.openx.in.write_time = 0;
423         io.openx.in.size = 0;
424         io.openx.in.timeout = 0;
425         status = smb_raw_open(cli->tree, mem_ctx, &io);
426         CHECK_STATUS(status, NT_STATUS_OK);
427         smbcli_close(cli->tree, io.openx.out.fnum);
428
429         /* check the extended return flag */
430         io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO | OPENX_FLAGS_EXTENDED_RETURN;
431         io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
432         status = smb_raw_open(cli->tree, mem_ctx, &io);
433         CHECK_STATUS(status, NT_STATUS_OK);
434         CHECK_VAL(io.openx.out.access_mask, SEC_STD_ALL);
435         smbcli_close(cli->tree, io.openx.out.fnum);
436
437 done:
438         smbcli_close(cli->tree, fnum);
439         smbcli_unlink(cli->tree, fname);
440
441         return ret;
442 }
443
444
445 /*
446   test RAW_OPEN_T2OPEN
447
448   I can't work out how to get win2003 to accept a create file via TRANS2_OPEN, which
449   is why you see all the ACCESS_DENIED results below. When we finally work this out then this
450   test will make more sense
451 */
452 static BOOL test_t2open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
453 {
454         union smb_open io;
455         union smb_fileinfo finfo;
456         const char *fname1 = BASEDIR "\\torture_t2open_yes.txt";
457         const char *fname2 = BASEDIR "\\torture_t2open_no.txt";
458         const char *fname = BASEDIR "\\torture_t2open_3.txt";
459         NTSTATUS status;
460         int fnum;
461         BOOL ret = True;
462         int i;
463         struct {
464                 uint16_t open_func;
465                 BOOL with_file;
466                 NTSTATUS correct_status;
467         } open_funcs[] = {
468                 { OPENX_OPEN_FUNC_OPEN,                           True,  NT_STATUS_OK },
469                 { OPENX_OPEN_FUNC_OPEN,                           False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
470                 { OPENX_OPEN_FUNC_OPEN  | OPENX_OPEN_FUNC_CREATE, True,  NT_STATUS_OK },
471                 { OPENX_OPEN_FUNC_OPEN  | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_ACCESS_DENIED },
472                 { OPENX_OPEN_FUNC_FAIL,                           True,  NT_STATUS_OBJECT_NAME_COLLISION },
473                 { OPENX_OPEN_FUNC_FAIL,                           False, NT_STATUS_ACCESS_DENIED },
474                 { OPENX_OPEN_FUNC_FAIL  | OPENX_OPEN_FUNC_CREATE, True,  NT_STATUS_OBJECT_NAME_COLLISION },
475                 { OPENX_OPEN_FUNC_FAIL  | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_ACCESS_DENIED },
476                 { OPENX_OPEN_FUNC_TRUNC,                          True,  NT_STATUS_ACCESS_DENIED },
477                 { OPENX_OPEN_FUNC_TRUNC,                          False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
478                 { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, True,  NT_STATUS_ACCESS_DENIED },
479                 { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_ACCESS_DENIED },
480         };
481
482         fnum = create_complex_file(cli, mem_ctx, fname1);
483         if (fnum == -1) {
484                 d_printf("Failed to create file %s - %s\n", fname1, smbcli_errstr(cli->tree));
485                 ret = False;
486                 goto done;
487         }
488         smbcli_close(cli->tree, fnum);
489
490         printf("Checking RAW_OPEN_T2OPEN\n");
491
492         io.t2open.level = RAW_OPEN_T2OPEN;
493         io.t2open.in.flags = OPENX_FLAGS_ADDITIONAL_INFO | 
494                 OPENX_FLAGS_EA_LEN | OPENX_FLAGS_EXTENDED_RETURN;
495         io.t2open.in.open_mode = OPENX_MODE_DENY_NONE | OPENX_MODE_ACCESS_RDWR;
496         io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
497         io.t2open.in.file_attrs = 0;
498         io.t2open.in.write_time = 0;
499         io.t2open.in.size = 0;
500         io.t2open.in.timeout = 0;
501
502         io.t2open.in.eas = talloc_p(mem_ctx, struct ea_struct);
503         io.t2open.in.num_eas = 1;
504         io.t2open.in.eas[0].flags = 0;
505         io.t2open.in.eas[0].name.s = "EAONE";
506         io.t2open.in.eas[0].value = data_blob_talloc(mem_ctx, "1", 1);
507
508         /* check all combinations of open_func */
509         for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
510                 if (open_funcs[i].with_file) {
511                         io.t2open.in.fname = fname1;
512                 } else {
513                         io.t2open.in.fname = fname2;
514                 }
515                 io.t2open.in.open_func = open_funcs[i].open_func;
516                 status = smb_raw_open(cli->tree, mem_ctx, &io);
517                 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
518                         printf("(%s) incorrect status %s should be %s (i=%d with_file=%d open_func=0x%x)\n", 
519                                __location__, nt_errstr(status), nt_errstr(open_funcs[i].correct_status),
520                                i, (int)open_funcs[i].with_file, (int)open_funcs[i].open_func);
521                         ret = False;
522                 }
523                 if (NT_STATUS_IS_OK(status)) {
524                         smbcli_close(cli->tree, io.t2open.out.fnum);
525                 }
526         }
527
528         smbcli_unlink(cli->tree, fname1);
529
530         /* check the basic return fields */
531         fnum = create_complex_file(cli, mem_ctx, fname);
532         smbcli_close(cli->tree, fnum);
533         io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
534         io.t2open.in.fname = fname;
535         status = smb_raw_open(cli->tree, mem_ctx, &io);
536         CHECK_STATUS(status, NT_STATUS_OK);
537         fnum = io.t2open.out.fnum;
538
539         CHECK_ALL_INFO(io.t2open.out.size, size);
540         CHECK_VAL(io.t2open.out.write_time, 0);
541         CHECK_ALL_INFO(io.t2open.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
542         CHECK_VAL(io.t2open.out.access, OPENX_MODE_DENY_NONE | OPENX_MODE_ACCESS_RDWR);
543         CHECK_VAL(io.t2open.out.ftype, 0);
544         CHECK_VAL(io.t2open.out.devstate, 0);
545         CHECK_VAL(io.t2open.out.action, OPENX_ACTION_EXISTED);
546         smbcli_close(cli->tree, fnum);
547
548         /* now check the search attrib for hidden files - win2003 ignores this? */
549         SET_ATTRIB(FILE_ATTRIBUTE_HIDDEN);
550         CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN, attrib);
551
552         status = smb_raw_open(cli->tree, mem_ctx, &io);
553         CHECK_STATUS(status, NT_STATUS_OK);
554         smbcli_close(cli->tree, io.t2open.out.fnum);
555
556         status = smb_raw_open(cli->tree, mem_ctx, &io);
557         CHECK_STATUS(status, NT_STATUS_OK);
558         smbcli_close(cli->tree, io.t2open.out.fnum);
559
560         SET_ATTRIB(FILE_ATTRIBUTE_NORMAL);
561         smbcli_unlink(cli->tree, fname);
562
563         /* and check attrib on create */
564         io.t2open.in.open_func = OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE;
565         io.t2open.in.file_attrs = FILE_ATTRIBUTE_SYSTEM;
566         status = smb_raw_open(cli->tree, mem_ctx, &io);
567         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
568
569         /* check timeout on create - win2003 ignores the timeout! */
570         io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
571         io.t2open.in.file_attrs = 0;
572         io.t2open.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_ALL;
573         status = smb_raw_open(cli->tree, mem_ctx, &io);
574         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
575
576 done:
577         smbcli_close(cli->tree, fnum);
578         smbcli_unlink(cli->tree, fname);
579
580         return ret;
581 }
582         
583
584 /*
585   test RAW_OPEN_NTCREATEX
586 */
587 static BOOL test_ntcreatex(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
588 {
589         union smb_open io;
590         union smb_fileinfo finfo;
591         const char *fname = BASEDIR "\\torture_ntcreatex.txt";
592         const char *dname = BASEDIR "\\torture_ntcreatex.dir";
593         NTSTATUS status;
594         int fnum = -1;
595         BOOL ret = True;
596         int i;
597         struct {
598                 uint32_t open_disp;
599                 BOOL with_file;
600                 NTSTATUS correct_status;
601         } open_funcs[] = {
602                 { NTCREATEX_DISP_SUPERSEDE,     True,  NT_STATUS_OK },
603                 { NTCREATEX_DISP_SUPERSEDE,     False, NT_STATUS_OK },
604                 { NTCREATEX_DISP_OPEN,          True,  NT_STATUS_OK },
605                 { NTCREATEX_DISP_OPEN,          False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
606                 { NTCREATEX_DISP_CREATE,        True,  NT_STATUS_OBJECT_NAME_COLLISION },
607                 { NTCREATEX_DISP_CREATE,        False, NT_STATUS_OK },
608                 { NTCREATEX_DISP_OPEN_IF,       True,  NT_STATUS_OK },
609                 { NTCREATEX_DISP_OPEN_IF,       False, NT_STATUS_OK },
610                 { NTCREATEX_DISP_OVERWRITE,     True,  NT_STATUS_OK },
611                 { NTCREATEX_DISP_OVERWRITE,     False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
612                 { NTCREATEX_DISP_OVERWRITE_IF,  True,  NT_STATUS_OK },
613                 { NTCREATEX_DISP_OVERWRITE_IF,  False, NT_STATUS_OK },
614                 { 6,                            True,  NT_STATUS_INVALID_PARAMETER },
615                 { 6,                            False, NT_STATUS_INVALID_PARAMETER },
616         };
617
618         printf("Checking RAW_OPEN_NTCREATEX\n");
619
620         /* reasonable default parameters */
621         io.generic.level = RAW_OPEN_NTCREATEX;
622         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
623         io.ntcreatex.in.root_fid = 0;
624         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
625         io.ntcreatex.in.alloc_size = 1024*1024;
626         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
627         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
628         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
629         io.ntcreatex.in.create_options = 0;
630         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
631         io.ntcreatex.in.security_flags = 0;
632         io.ntcreatex.in.fname = fname;
633
634         /* test the open disposition */
635         for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
636                 if (open_funcs[i].with_file) {
637                         fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR|O_TRUNC, DENY_NONE);
638                         if (fnum == -1) {
639                                 d_printf("Failed to create file %s - %s\n", fname, smbcli_errstr(cli->tree));
640                                 ret = False;
641                                 goto done;
642                         }
643                         smbcli_close(cli->tree, fnum);
644                 }
645                 io.ntcreatex.in.open_disposition = open_funcs[i].open_disp;
646                 status = smb_raw_open(cli->tree, mem_ctx, &io);
647                 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
648                         printf("(%s) incorrect status %s should be %s (i=%d with_file=%d open_disp=%d)\n", 
649                                __location__, nt_errstr(status), nt_errstr(open_funcs[i].correct_status),
650                                i, (int)open_funcs[i].with_file, (int)open_funcs[i].open_disp);
651                         ret = False;
652                 }
653                 if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
654                         smbcli_close(cli->tree, io.ntcreatex.out.fnum);
655                         smbcli_unlink(cli->tree, fname);
656                 }
657         }
658
659         /* basic field testing */
660         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
661
662         status = smb_raw_open(cli->tree, mem_ctx, &io);
663         CHECK_STATUS(status, NT_STATUS_OK);
664         fnum = io.ntcreatex.out.fnum;
665
666         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
667         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
668         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
669         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
670         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
671         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
672         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
673         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
674         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
675         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
676         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
677
678         /* check fields when the file already existed */
679         smbcli_close(cli->tree, fnum);
680         smbcli_unlink(cli->tree, fname);
681         fnum = create_complex_file(cli, mem_ctx, fname);
682         if (fnum == -1) {
683                 ret = False;
684                 goto done;
685         }
686         smbcli_close(cli->tree, fnum);
687
688         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
689         status = smb_raw_open(cli->tree, mem_ctx, &io);
690         CHECK_STATUS(status, NT_STATUS_OK);
691         fnum = io.ntcreatex.out.fnum;
692
693         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
694         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
695         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
696         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
697         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
698         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
699         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
700         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
701         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
702         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
703         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
704         smbcli_close(cli->tree, fnum);
705         smbcli_unlink(cli->tree, fname);
706
707
708         /* create a directory */
709         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
710         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
711         io.ntcreatex.in.alloc_size = 0;
712         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
713         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
714         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
715         io.ntcreatex.in.create_options = 0;
716         io.ntcreatex.in.fname = dname;
717         fname = dname;
718
719         smbcli_rmdir(cli->tree, fname);
720         smbcli_unlink(cli->tree, fname);
721
722         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
723         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
724         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
725         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
726         status = smb_raw_open(cli->tree, mem_ctx, &io);
727         CHECK_STATUS(status, NT_STATUS_OK);
728         fnum = io.ntcreatex.out.fnum;
729
730         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
731         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
732         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
733         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
734         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
735         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
736         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
737         CHECK_VAL(io.ntcreatex.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED, 
738                   FILE_ATTRIBUTE_DIRECTORY);
739         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
740         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
741         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
742         CHECK_VAL(io.ntcreatex.out.is_directory, 1);
743         CHECK_VAL(io.ntcreatex.out.size, 0);
744         CHECK_VAL(io.ntcreatex.out.alloc_size, 0);
745         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
746         smbcli_unlink(cli->tree, fname);
747         
748
749 done:
750         smbcli_close(cli->tree, fnum);
751         smbcli_unlink(cli->tree, fname);
752
753         return ret;
754 }
755
756
757 /*
758   test RAW_OPEN_NTTRANS_CREATE
759 */
760 static BOOL test_nttrans_create(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
761 {
762         union smb_open io;
763         union smb_fileinfo finfo;
764         const char *fname = BASEDIR "\\torture_ntcreatex.txt";
765         const char *dname = BASEDIR "\\torture_ntcreatex.dir";
766         NTSTATUS status;
767         int fnum = -1;
768         BOOL ret = True;
769         int i;
770         struct {
771                 uint32_t open_disp;
772                 BOOL with_file;
773                 NTSTATUS correct_status;
774         } open_funcs[] = {
775                 { NTCREATEX_DISP_SUPERSEDE,     True,  NT_STATUS_OK },
776                 { NTCREATEX_DISP_SUPERSEDE,     False, NT_STATUS_OK },
777                 { NTCREATEX_DISP_OPEN,          True,  NT_STATUS_OK },
778                 { NTCREATEX_DISP_OPEN,          False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
779                 { NTCREATEX_DISP_CREATE,        True,  NT_STATUS_OBJECT_NAME_COLLISION },
780                 { NTCREATEX_DISP_CREATE,        False, NT_STATUS_OK },
781                 { NTCREATEX_DISP_OPEN_IF,       True,  NT_STATUS_OK },
782                 { NTCREATEX_DISP_OPEN_IF,       False, NT_STATUS_OK },
783                 { NTCREATEX_DISP_OVERWRITE,     True,  NT_STATUS_OK },
784                 { NTCREATEX_DISP_OVERWRITE,     False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
785                 { NTCREATEX_DISP_OVERWRITE_IF,  True,  NT_STATUS_OK },
786                 { NTCREATEX_DISP_OVERWRITE_IF,  False, NT_STATUS_OK },
787                 { 6,                            True,  NT_STATUS_INVALID_PARAMETER },
788                 { 6,                            False, NT_STATUS_INVALID_PARAMETER },
789         };
790
791         printf("Checking RAW_OPEN_NTTRANS_CREATE\n");
792
793         /* reasonable default parameters */
794         io.generic.level = RAW_OPEN_NTTRANS_CREATE;
795         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
796         io.ntcreatex.in.root_fid = 0;
797         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
798         io.ntcreatex.in.alloc_size = 1024*1024;
799         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
800         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
801         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
802         io.ntcreatex.in.create_options = 0;
803         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
804         io.ntcreatex.in.security_flags = 0;
805         io.ntcreatex.in.fname = fname;
806         io.ntcreatex.in.sec_desc = NULL;
807         io.ntcreatex.in.ea_list = NULL;
808
809         /* test the open disposition */
810         for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
811                 if (open_funcs[i].with_file) {
812                         fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR|O_TRUNC, DENY_NONE);
813                         if (fnum == -1) {
814                                 d_printf("Failed to create file %s - %s\n", fname, smbcli_errstr(cli->tree));
815                                 ret = False;
816                                 goto done;
817                         }
818                         smbcli_close(cli->tree, fnum);
819                 }
820                 io.ntcreatex.in.open_disposition = open_funcs[i].open_disp;
821                 status = smb_raw_open(cli->tree, mem_ctx, &io);
822                 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
823                         printf("(%s) incorrect status %s should be %s (i=%d with_file=%d open_disp=%d)\n", 
824                                __location__, nt_errstr(status), nt_errstr(open_funcs[i].correct_status),
825                                i, (int)open_funcs[i].with_file, (int)open_funcs[i].open_disp);
826                         ret = False;
827                 }
828                 if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
829                         smbcli_close(cli->tree, io.ntcreatex.out.fnum);
830                         smbcli_unlink(cli->tree, fname);
831                 }
832         }
833
834         /* basic field testing */
835         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
836
837         status = smb_raw_open(cli->tree, mem_ctx, &io);
838         CHECK_STATUS(status, NT_STATUS_OK);
839         fnum = io.ntcreatex.out.fnum;
840
841         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
842         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
843         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
844         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
845         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
846         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
847         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
848         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
849         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
850         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
851         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
852
853         /* check fields when the file already existed */
854         smbcli_close(cli->tree, fnum);
855         smbcli_unlink(cli->tree, fname);
856         fnum = create_complex_file(cli, mem_ctx, fname);
857         if (fnum == -1) {
858                 ret = False;
859                 goto done;
860         }
861         smbcli_close(cli->tree, fnum);
862
863         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
864         status = smb_raw_open(cli->tree, mem_ctx, &io);
865         CHECK_STATUS(status, NT_STATUS_OK);
866         fnum = io.ntcreatex.out.fnum;
867
868         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
869         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
870         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
871         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
872         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
873         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
874         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
875         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
876         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
877         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
878         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
879         smbcli_close(cli->tree, fnum);
880         smbcli_unlink(cli->tree, fname);
881
882
883         /* create a directory */
884         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
885         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
886         io.ntcreatex.in.alloc_size = 0;
887         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
888         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
889         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
890         io.ntcreatex.in.create_options = 0;
891         io.ntcreatex.in.fname = dname;
892         fname = dname;
893
894         smbcli_rmdir(cli->tree, fname);
895         smbcli_unlink(cli->tree, fname);
896
897         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
898         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
899         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
900         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
901         status = smb_raw_open(cli->tree, mem_ctx, &io);
902         CHECK_STATUS(status, NT_STATUS_OK);
903         fnum = io.ntcreatex.out.fnum;
904
905         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
906         CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
907         CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
908         CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
909         CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
910         CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
911         CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
912         CHECK_VAL(io.ntcreatex.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED, 
913                   FILE_ATTRIBUTE_DIRECTORY);
914         CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
915         CHECK_ALL_INFO(io.ntcreatex.out.size, size);
916         CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
917         CHECK_VAL(io.ntcreatex.out.is_directory, 1);
918         CHECK_VAL(io.ntcreatex.out.size, 0);
919         CHECK_VAL(io.ntcreatex.out.alloc_size, 0);
920         CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
921         smbcli_unlink(cli->tree, fname);
922         
923
924 done:
925         smbcli_close(cli->tree, fnum);
926         smbcli_unlink(cli->tree, fname);
927
928         return ret;
929 }
930
931 /*
932   test RAW_OPEN_NTCREATEX with an already opened and byte range locked file
933
934   I've got an application that does a similar sequence of ntcreate&x,
935   locking&x and another ntcreate&x with
936   open_disposition==NTCREATEX_DISP_OVERWRITE_IF. Windows 2003 allows the
937   second open.
938 */
939 static BOOL test_ntcreatex_brlocked(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
940 {
941         union smb_open io, io1;
942         union smb_lock io2;
943         struct smb_lock_entry lock[1];
944         const char *fname = BASEDIR "\\torture_ntcreatex.txt";
945         NTSTATUS status;
946         BOOL ret = True;
947
948         /* reasonable default parameters */
949         io.generic.level = RAW_OPEN_NTCREATEX;
950         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
951         io.ntcreatex.in.root_fid = 0;
952         io.ntcreatex.in.access_mask = 0x2019f;
953         io.ntcreatex.in.alloc_size = 0;
954         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
955         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
956                 NTCREATEX_SHARE_ACCESS_WRITE;
957         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
958         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
959         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
960         io.ntcreatex.in.security_flags = NTCREATEX_SECURITY_DYNAMIC |
961                 NTCREATEX_SECURITY_ALL;
962         io.ntcreatex.in.fname = fname;
963
964         status = smb_raw_open(cli->tree, mem_ctx, &io);
965         CHECK_STATUS(status, NT_STATUS_OK);
966
967         io2.lockx.level = RAW_LOCK_LOCKX;
968         io2.lockx.in.fnum = io.ntcreatex.out.fnum;
969         io2.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
970         io2.lockx.in.timeout = 0;
971         io2.lockx.in.ulock_cnt = 0;
972         io2.lockx.in.lock_cnt = 1;
973         lock[0].pid = cli->session->pid;
974         lock[0].offset = 0;
975         lock[0].count = 0x1;
976         io2.lockx.in.locks = &lock[0];
977         status = smb_raw_lock(cli->tree, &io2);
978         CHECK_STATUS(status, NT_STATUS_OK);
979
980         io1.generic.level = RAW_OPEN_NTCREATEX;
981         io1.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
982         io1.ntcreatex.in.root_fid = 0;
983         io1.ntcreatex.in.access_mask = 0x20196;
984         io1.ntcreatex.in.alloc_size = 0;
985         io1.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
986         io1.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
987                 NTCREATEX_SHARE_ACCESS_WRITE;
988         io1.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
989         io1.ntcreatex.in.create_options = 0;
990         io1.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
991         io1.ntcreatex.in.security_flags = NTCREATEX_SECURITY_DYNAMIC |
992                 NTCREATEX_SECURITY_ALL;
993         io1.ntcreatex.in.fname = fname;
994
995         status = smb_raw_open(cli->tree, mem_ctx, &io1);
996         CHECK_STATUS(status, NT_STATUS_OK);
997
998  done:
999         smbcli_close(cli->tree, io.ntcreatex.out.fnum);
1000         smbcli_close(cli->tree, io1.ntcreatex.out.fnum);
1001         smbcli_unlink(cli->tree, fname);
1002         return ret;
1003 }
1004
1005 /*
1006   test RAW_OPEN_MKNEW
1007 */
1008 static BOOL test_mknew(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
1009 {
1010         union smb_open io;
1011         const char *fname = BASEDIR "\\torture_mknew.txt";
1012         NTSTATUS status;
1013         int fnum = -1;
1014         BOOL ret = True;
1015         time_t basetime = (time(NULL) + 3600*24*3) & ~1;
1016         union smb_fileinfo finfo;
1017
1018         printf("Checking RAW_OPEN_MKNEW\n");
1019
1020         io.mknew.level = RAW_OPEN_MKNEW;
1021         io.mknew.in.attrib = 0;
1022         io.mknew.in.write_time = 0;
1023         io.mknew.in.fname = fname;
1024         status = smb_raw_open(cli->tree, mem_ctx, &io);
1025         CHECK_STATUS(status, NT_STATUS_OK);
1026         fnum = io.mknew.out.fnum;
1027
1028         status = smb_raw_open(cli->tree, mem_ctx, &io);
1029         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
1030
1031         smbcli_close(cli->tree, fnum);
1032         smbcli_unlink(cli->tree, fname);
1033
1034         /* make sure write_time works */
1035         io.mknew.in.write_time = basetime;
1036         status = smb_raw_open(cli->tree, mem_ctx, &io);
1037         CHECK_STATUS(status, NT_STATUS_OK);
1038         fnum = io.mknew.out.fnum;
1039         CHECK_TIME(basetime, write_time);
1040
1041         smbcli_close(cli->tree, fnum);
1042         smbcli_unlink(cli->tree, fname);
1043
1044         /* make sure file_attrs works */
1045         io.mknew.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1046         status = smb_raw_open(cli->tree, mem_ctx, &io);
1047         CHECK_STATUS(status, NT_STATUS_OK);
1048         fnum = io.mknew.out.fnum;
1049         CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE, 
1050                        attrib & ~FILE_ATTRIBUTE_NONINDEXED);
1051         
1052 done:
1053         smbcli_close(cli->tree, fnum);
1054         smbcli_unlink(cli->tree, fname);
1055
1056         return ret;
1057 }
1058
1059
1060 /*
1061   test RAW_OPEN_CREATE
1062 */
1063 static BOOL test_create(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
1064 {
1065         union smb_open io;
1066         const char *fname = BASEDIR "\\torture_create.txt";
1067         NTSTATUS status;
1068         int fnum = -1;
1069         BOOL ret = True;
1070         time_t basetime = (time(NULL) + 3600*24*3) & ~1;
1071         union smb_fileinfo finfo;
1072
1073         printf("Checking RAW_OPEN_CREATE\n");
1074
1075         io.create.level = RAW_OPEN_CREATE;
1076         io.create.in.attrib = 0;
1077         io.create.in.write_time = 0;
1078         io.create.in.fname = fname;
1079         status = smb_raw_open(cli->tree, mem_ctx, &io);
1080         CHECK_STATUS(status, NT_STATUS_OK);
1081         fnum = io.create.out.fnum;
1082
1083         status = smb_raw_open(cli->tree, mem_ctx, &io);
1084         CHECK_STATUS(status, NT_STATUS_OK);
1085
1086         smbcli_close(cli->tree, io.create.out.fnum);
1087         smbcli_close(cli->tree, fnum);
1088         smbcli_unlink(cli->tree, fname);
1089
1090         /* make sure write_time works */
1091         io.create.in.write_time = basetime;
1092         status = smb_raw_open(cli->tree, mem_ctx, &io);
1093         CHECK_STATUS(status, NT_STATUS_OK);
1094         fnum = io.create.out.fnum;
1095         CHECK_TIME(basetime, write_time);
1096
1097         smbcli_close(cli->tree, fnum);
1098         smbcli_unlink(cli->tree, fname);
1099
1100         /* make sure file_attrs works */
1101         io.create.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1102         status = smb_raw_open(cli->tree, mem_ctx, &io);
1103         CHECK_STATUS(status, NT_STATUS_OK);
1104         fnum = io.create.out.fnum;
1105         CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE, 
1106                        attrib & ~FILE_ATTRIBUTE_NONINDEXED);
1107         
1108 done:
1109         smbcli_close(cli->tree, fnum);
1110         smbcli_unlink(cli->tree, fname);
1111
1112         return ret;
1113 }
1114
1115
1116 /*
1117   test RAW_OPEN_CTEMP
1118 */
1119 static BOOL test_ctemp(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
1120 {
1121         union smb_open io;
1122         NTSTATUS status;
1123         int fnum = -1;
1124         BOOL ret = True;
1125         time_t basetime = (time(NULL) + 3600*24*3) & ~1;
1126         union smb_fileinfo finfo;
1127         const char *name, *fname = NULL;
1128
1129         printf("Checking RAW_OPEN_CTEMP\n");
1130
1131         io.ctemp.level = RAW_OPEN_CTEMP;
1132         io.ctemp.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1133         io.ctemp.in.write_time = basetime;
1134         io.ctemp.in.directory = BASEDIR;
1135         status = smb_raw_open(cli->tree, mem_ctx, &io);
1136         CHECK_STATUS(status, NT_STATUS_OK);
1137         fnum = io.ctemp.out.fnum;
1138
1139         name = io.ctemp.out.name;
1140
1141         finfo.generic.level = RAW_FILEINFO_NAME_INFO;
1142         finfo.generic.in.fnum = fnum;
1143         status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo);
1144         CHECK_STATUS(status, NT_STATUS_OK);
1145
1146         fname = finfo.name_info.out.fname.s;
1147         d_printf("ctemp name=%s  real name=%s\n", name, fname);
1148
1149 done:
1150         smbcli_close(cli->tree, fnum);
1151         if (fname) {
1152                 smbcli_unlink(cli->tree, fname);
1153         }
1154
1155         return ret;
1156 }
1157
1158 /* basic testing of all RAW_OPEN_* calls 
1159 */
1160 BOOL torture_raw_open(void)
1161 {
1162         struct smbcli_state *cli;
1163         BOOL ret = True;
1164         TALLOC_CTX *mem_ctx;
1165
1166         if (!torture_open_connection(&cli)) {
1167                 return False;
1168         }
1169
1170         mem_ctx = talloc_init("torture_raw_open");
1171
1172         if (!torture_setup_dir(cli, BASEDIR)) {
1173                 return False;
1174         }
1175
1176         ret &= test_ntcreatex_brlocked(cli, mem_ctx);
1177         ret &= test_open(cli, mem_ctx);
1178         ret &= test_openx(cli, mem_ctx);
1179         ret &= test_ntcreatex(cli, mem_ctx);
1180         ret &= test_nttrans_create(cli, mem_ctx);
1181         ret &= test_t2open(cli, mem_ctx);
1182         ret &= test_mknew(cli, mem_ctx);
1183         ret &= test_create(cli, mem_ctx);
1184         ret &= test_ctemp(cli, mem_ctx);
1185
1186         smb_raw_exit(cli->session);
1187         smbcli_deltree(cli->tree, BASEDIR);
1188
1189         torture_close_connection(cli);
1190         talloc_destroy(mem_ctx);
1191         return ret;
1192 }