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