r12499: Move smb_build.h out of includes.h
[kai/samba-autobuild/.git] / source4 / torture / torture.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-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 "clilist.h"
23 #include "lib/cmdline/popt_common.h"
24 #include "libcli/raw/libcliraw.h"
25 #include "system/time.h"
26 #include "system/wait.h"
27 #include "system/filesys.h"
28 #include "ioctl.h"
29 #include "librpc/gen_ndr/ndr_security.h"
30 #include "smb_build.h"
31
32 int torture_nprocs=4;
33 int torture_numops=10;
34 int torture_entries=1000;
35 int torture_failures=1;
36 int torture_seed=0;
37 static int procnum; /* records process count number when forking */
38 static struct smbcli_state *current_cli;
39 static BOOL use_oplocks;
40 static BOOL use_level_II_oplocks;
41
42 BOOL torture_showall = False;
43
44 #define CHECK_MAX_FAILURES(label) do { if (++failures >= torture_failures) goto label; } while (0)
45
46 static struct smbcli_state *open_nbt_connection(void)
47 {
48         struct nbt_name called, calling;
49         struct smbcli_state *cli;
50         const char *host = lp_parm_string(-1, "torture", "host");
51
52         make_nbt_name_client(&calling, lp_netbios_name());
53
54         nbt_choose_called_name(NULL, &called, host, NBT_NAME_SERVER);
55
56         cli = smbcli_state_init(NULL);
57         if (!cli) {
58                 printf("Failed initialize smbcli_struct to connect with %s\n", host);
59                 goto failed;
60         }
61
62         if (!smbcli_socket_connect(cli, host)) {
63                 printf("Failed to connect with %s\n", host);
64                 goto failed;
65         }
66
67         if (!smbcli_transport_establish(cli, &calling, &called)) {
68                 printf("%s rejected the session\n",host);
69                 goto failed;
70         }
71
72         return cli;
73
74 failed:
75         talloc_free(cli);
76         return NULL;
77 }
78
79 BOOL torture_open_connection_share(TALLOC_CTX *mem_ctx,
80                                    struct smbcli_state **c, 
81                                    const char *hostname, 
82                                    const char *sharename,
83                                    struct event_context *ev)
84 {
85         NTSTATUS status;
86
87         status = smbcli_full_connection(mem_ctx, c, hostname, 
88                                         sharename, NULL,
89                                         cmdline_credentials, ev);
90         if (!NT_STATUS_IS_OK(status)) {
91                 printf("Failed to open connection - %s\n", nt_errstr(status));
92                 return False;
93         }
94
95         (*c)->transport->options.use_oplocks = use_oplocks;
96         (*c)->transport->options.use_level2_oplocks = use_level_II_oplocks;
97
98         return True;
99 }
100
101 BOOL torture_open_connection(struct smbcli_state **c)
102 {
103         const char *host = lp_parm_string(-1, "torture", "host");
104         const char *share = lp_parm_string(-1, "torture", "share");
105
106         return torture_open_connection_share(NULL, c, host, share, NULL);
107 }
108
109
110
111 BOOL torture_close_connection(struct smbcli_state *c)
112 {
113         BOOL ret = True;
114         if (!c) return True;
115         if (NT_STATUS_IS_ERR(smbcli_tdis(c))) {
116                 printf("tdis failed (%s)\n", smbcli_errstr(c->tree));
117                 ret = False;
118         }
119         talloc_free(c);
120         return ret;
121 }
122
123 /* open a rpc connection to the chosen binding string */
124 NTSTATUS torture_rpc_connection(TALLOC_CTX *parent_ctx, 
125                                 struct dcerpc_pipe **p, 
126                                 const char *pipe_name,
127                                 const char *pipe_uuid, 
128                                 uint32_t pipe_version)
129 {
130         NTSTATUS status;
131         const char *binding = lp_parm_string(-1, "torture", "binding");
132
133         if (!binding) {
134                 printf("You must specify a ncacn binding string\n");
135                 return NT_STATUS_INVALID_PARAMETER;
136         }
137
138         status = dcerpc_pipe_connect(parent_ctx, 
139                                      p, binding, pipe_uuid, pipe_version,
140                                      cmdline_credentials, NULL);
141  
142         return status;
143 }
144
145 /* open a rpc connection to a specific transport */
146 NTSTATUS torture_rpc_connection_transport(TALLOC_CTX *parent_ctx, 
147                                           struct dcerpc_pipe **p, 
148                                           const char *pipe_name,
149                                           const char *pipe_uuid, 
150                                           uint32_t pipe_version,
151                                           enum dcerpc_transport_t transport)
152 {
153         NTSTATUS status;
154         const char *binding = lp_parm_string(-1, "torture", "binding");
155         struct dcerpc_binding *b;
156         TALLOC_CTX *mem_ctx = talloc_named(parent_ctx, 0, "torture_rpc_connection_smb");
157
158         if (!binding) {
159                 printf("You must specify a ncacn binding string\n");
160                 talloc_free(mem_ctx);
161                 return NT_STATUS_INVALID_PARAMETER;
162         }
163
164         status = dcerpc_parse_binding(mem_ctx, binding, &b);
165         if (!NT_STATUS_IS_OK(status)) {
166                 DEBUG(0,("Failed to parse dcerpc binding '%s'\n", binding));
167                 talloc_free(mem_ctx);
168                 return status;
169         }
170
171         b->transport = transport;
172
173         status = dcerpc_pipe_connect_b(mem_ctx, p, b, pipe_uuid, pipe_version,
174                                        cmdline_credentials, NULL);
175                                            
176         if (NT_STATUS_IS_OK(status)) {
177                 *p = talloc_reference(parent_ctx, *p);
178         } else {
179                 *p = NULL;
180         }
181         talloc_free(mem_ctx);
182         return status;
183 }
184
185 /* check if the server produced the expected error code */
186 BOOL check_error(const char *location, struct smbcli_state *c, 
187                  uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
188 {
189         NTSTATUS status;
190         
191         status = smbcli_nt_error(c->tree);
192         if (NT_STATUS_IS_DOS(status)) {
193                 int class, num;
194                 class = NT_STATUS_DOS_CLASS(status);
195                 num = NT_STATUS_DOS_CODE(status);
196                 if (eclass != class || ecode != num) {
197                         printf("unexpected error code %s\n", nt_errstr(status));
198                         printf(" expected %s or %s (at %s)\n", 
199                                nt_errstr(NT_STATUS_DOS(eclass, ecode)), 
200                                nt_errstr(nterr), location);
201                         return False;
202                 }
203         } else {
204                 if (!NT_STATUS_EQUAL(nterr, status)) {
205                         printf("unexpected error code %s\n", nt_errstr(status));
206                         printf(" expected %s (at %s)\n", nt_errstr(nterr), location);
207                         return False;
208                 }
209         }
210
211         return True;
212 }
213
214
215 static BOOL wait_lock(struct smbcli_state *c, int fnum, uint32_t offset, uint32_t len)
216 {
217         while (NT_STATUS_IS_ERR(smbcli_lock(c->tree, fnum, offset, len, -1, WRITE_LOCK))) {
218                 if (!check_error(__location__, c, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
219         }
220         return True;
221 }
222
223
224 static BOOL rw_torture(struct smbcli_state *c)
225 {
226         const char *lockfname = "\\torture.lck";
227         char *fname;
228         int fnum;
229         int fnum2;
230         pid_t pid2, pid = getpid();
231         int i, j;
232         uint8_t buf[1024];
233         BOOL correct = True;
234
235         fnum2 = smbcli_open(c->tree, lockfname, O_RDWR | O_CREAT | O_EXCL, 
236                          DENY_NONE);
237         if (fnum2 == -1)
238                 fnum2 = smbcli_open(c->tree, lockfname, O_RDWR, DENY_NONE);
239         if (fnum2 == -1) {
240                 printf("open of %s failed (%s)\n", lockfname, smbcli_errstr(c->tree));
241                 return False;
242         }
243
244
245         for (i=0;i<torture_numops;i++) {
246                 uint_t n = (uint_t)random()%10;
247                 if (i % 10 == 0) {
248                         printf("%d\r", i); fflush(stdout);
249                 }
250                 asprintf(&fname, "\\torture.%u", n);
251
252                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
253                         return False;
254                 }
255
256                 fnum = smbcli_open(c->tree, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
257                 if (fnum == -1) {
258                         printf("open failed (%s)\n", smbcli_errstr(c->tree));
259                         correct = False;
260                         break;
261                 }
262
263                 if (smbcli_write(c->tree, fnum, 0, &pid, 0, sizeof(pid)) != sizeof(pid)) {
264                         printf("write failed (%s)\n", smbcli_errstr(c->tree));
265                         correct = False;
266                 }
267
268                 for (j=0;j<50;j++) {
269                         if (smbcli_write(c->tree, fnum, 0, buf, 
270                                       sizeof(pid)+(j*sizeof(buf)), 
271                                       sizeof(buf)) != sizeof(buf)) {
272                                 printf("write failed (%s)\n", smbcli_errstr(c->tree));
273                                 correct = False;
274                         }
275                 }
276
277                 pid2 = 0;
278
279                 if (smbcli_read(c->tree, fnum, &pid2, 0, sizeof(pid)) != sizeof(pid)) {
280                         printf("read failed (%s)\n", smbcli_errstr(c->tree));
281                         correct = False;
282                 }
283
284                 if (pid2 != pid) {
285                         printf("data corruption!\n");
286                         correct = False;
287                 }
288
289                 if (NT_STATUS_IS_ERR(smbcli_close(c->tree, fnum))) {
290                         printf("close failed (%s)\n", smbcli_errstr(c->tree));
291                         correct = False;
292                 }
293
294                 if (NT_STATUS_IS_ERR(smbcli_unlink(c->tree, fname))) {
295                         printf("unlink failed (%s)\n", smbcli_errstr(c->tree));
296                         correct = False;
297                 }
298
299                 if (NT_STATUS_IS_ERR(smbcli_unlock(c->tree, fnum2, n*sizeof(int), sizeof(int)))) {
300                         printf("unlock failed (%s)\n", smbcli_errstr(c->tree));
301                         correct = False;
302                 }
303                 free(fname);
304         }
305
306         smbcli_close(c->tree, fnum2);
307         smbcli_unlink(c->tree, lockfname);
308
309         printf("%d\n", i);
310
311         return correct;
312 }
313
314 static BOOL run_torture(struct smbcli_state *cli, int dummy)
315 {
316         BOOL ret;
317
318         ret = rw_torture(cli);
319         
320         if (!torture_close_connection(cli)) {
321                 ret = False;
322         }
323
324         return ret;
325 }
326
327
328 static BOOL rw_torture2(struct smbcli_state *c1, struct smbcli_state *c2)
329 {
330         const char *lockfname = "\\torture2.lck";
331         int fnum1;
332         int fnum2;
333         int i;
334         uint8_t buf[131072];
335         uint8_t buf_rd[131072];
336         BOOL correct = True;
337         ssize_t bytes_read, bytes_written;
338
339         if (smbcli_deltree(c1->tree, lockfname) == -1) {
340                 printf("unlink failed (%s)\n", smbcli_errstr(c1->tree));
341         }
342
343         fnum1 = smbcli_open(c1->tree, lockfname, O_RDWR | O_CREAT | O_EXCL, 
344                          DENY_NONE);
345         if (fnum1 == -1) {
346                 printf("first open read/write of %s failed (%s)\n",
347                                 lockfname, smbcli_errstr(c1->tree));
348                 return False;
349         }
350         fnum2 = smbcli_open(c2->tree, lockfname, O_RDONLY, 
351                          DENY_NONE);
352         if (fnum2 == -1) {
353                 printf("second open read-only of %s failed (%s)\n",
354                                 lockfname, smbcli_errstr(c2->tree));
355                 smbcli_close(c1->tree, fnum1);
356                 return False;
357         }
358
359         printf("Checking data integrity over %d ops\n", torture_numops);
360
361         for (i=0;i<torture_numops;i++)
362         {
363                 size_t buf_size = ((uint_t)random()%(sizeof(buf)-1))+ 1;
364                 if (i % 10 == 0) {
365                         printf("%d\r", i); fflush(stdout);
366                 }
367
368                 generate_random_buffer(buf, buf_size);
369
370                 if ((bytes_written = smbcli_write(c1->tree, fnum1, 0, buf, 0, buf_size)) != buf_size) {
371                         printf("write failed (%s)\n", smbcli_errstr(c1->tree));
372                         printf("wrote %d, expected %d\n", (int)bytes_written, (int)buf_size); 
373                         correct = False;
374                         break;
375                 }
376
377                 if ((bytes_read = smbcli_read(c2->tree, fnum2, buf_rd, 0, buf_size)) != buf_size) {
378                         printf("read failed (%s)\n", smbcli_errstr(c2->tree));
379                         printf("read %d, expected %d\n", (int)bytes_read, (int)buf_size); 
380                         correct = False;
381                         break;
382                 }
383
384                 if (memcmp(buf_rd, buf, buf_size) != 0)
385                 {
386                         printf("read/write compare failed\n");
387                         correct = False;
388                         break;
389                 }
390         }
391
392         if (NT_STATUS_IS_ERR(smbcli_close(c2->tree, fnum2))) {
393                 printf("close failed (%s)\n", smbcli_errstr(c2->tree));
394                 correct = False;
395         }
396         if (NT_STATUS_IS_ERR(smbcli_close(c1->tree, fnum1))) {
397                 printf("close failed (%s)\n", smbcli_errstr(c1->tree));
398                 correct = False;
399         }
400
401         if (NT_STATUS_IS_ERR(smbcli_unlink(c1->tree, lockfname))) {
402                 printf("unlink failed (%s)\n", smbcli_errstr(c1->tree));
403                 correct = False;
404         }
405
406         return correct;
407 }
408
409 #define BOOLSTR(b) ((b) ? "Yes" : "No")
410
411 static BOOL run_readwritetest(void)
412 {
413         struct smbcli_state *cli1, *cli2;
414         BOOL test1, test2 = True;
415
416         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
417                 return False;
418         }
419
420         printf("starting readwritetest\n");
421
422         test1 = rw_torture2(cli1, cli2);
423         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
424
425         if (test1) {
426                 test2 = rw_torture2(cli1, cli1);
427                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
428         }
429
430         if (!torture_close_connection(cli1)) {
431                 test1 = False;
432         }
433
434         if (!torture_close_connection(cli2)) {
435                 test2 = False;
436         }
437
438         return (test1 && test2);
439 }
440
441 /*
442   this checks to see if a secondary tconx can use open files from an
443   earlier tconx
444  */
445 static BOOL run_tcon_test(void)
446 {
447         struct smbcli_state *cli;
448         const char *fname = "\\tcontest.tmp";
449         int fnum1;
450         uint16_t cnum1, cnum2, cnum3;
451         uint16_t vuid1, vuid2;
452         uint8_t buf[4];
453         BOOL ret = True;
454         struct smbcli_tree *tree1;
455         const char *host = lp_parm_string(-1, "torture", "host");
456         const char *share = lp_parm_string(-1, "torture", "share");
457         const char *password = lp_parm_string(-1, "torture", "password");
458
459         if (!torture_open_connection(&cli)) {
460                 return False;
461         }
462
463         printf("starting tcontest\n");
464
465         if (smbcli_deltree(cli->tree, fname) == -1) {
466                 printf("unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
467         }
468
469         fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
470         if (fnum1 == -1) {
471                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
472                 return False;
473         }
474
475         cnum1 = cli->tree->tid;
476         vuid1 = cli->session->vuid;
477
478         memset(&buf, 0, 4); /* init buf so valgrind won't complain */
479         if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) != 4) {
480                 printf("initial write failed (%s)\n", smbcli_errstr(cli->tree));
481                 return False;
482         }
483
484         tree1 = cli->tree;      /* save old tree connection */
485         if (NT_STATUS_IS_ERR(smbcli_tconX(cli, share, "?????", password))) {
486                 printf("%s refused 2nd tree connect (%s)\n", host,
487                            smbcli_errstr(cli->tree));
488                 talloc_free(cli);
489                 return False;
490         }
491
492         cnum2 = cli->tree->tid;
493         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
494         vuid2 = cli->session->vuid + 1;
495
496         /* try a write with the wrong tid */
497         cli->tree->tid = cnum2;
498
499         if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
500                 printf("* server allows write with wrong TID\n");
501                 ret = False;
502         } else {
503                 printf("server fails write with wrong TID : %s\n", smbcli_errstr(cli->tree));
504         }
505
506
507         /* try a write with an invalid tid */
508         cli->tree->tid = cnum3;
509
510         if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
511                 printf("* server allows write with invalid TID\n");
512                 ret = False;
513         } else {
514                 printf("server fails write with invalid TID : %s\n", smbcli_errstr(cli->tree));
515         }
516
517         /* try a write with an invalid vuid */
518         cli->session->vuid = vuid2;
519         cli->tree->tid = cnum1;
520
521         if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
522                 printf("* server allows write with invalid VUID\n");
523                 ret = False;
524         } else {
525                 printf("server fails write with invalid VUID : %s\n", smbcli_errstr(cli->tree));
526         }
527
528         cli->session->vuid = vuid1;
529         cli->tree->tid = cnum1;
530
531         if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum1))) {
532                 printf("close failed (%s)\n", smbcli_errstr(cli->tree));
533                 return False;
534         }
535
536         cli->tree->tid = cnum2;
537
538         if (NT_STATUS_IS_ERR(smbcli_tdis(cli))) {
539                 printf("secondary tdis failed (%s)\n", smbcli_errstr(cli->tree));
540                 return False;
541         }
542
543         cli->tree = tree1;  /* restore initial tree */
544         cli->tree->tid = cnum1;
545
546         smbcli_unlink(tree1, fname);
547
548         if (!torture_close_connection(cli)) {
549                 return False;
550         }
551
552         return ret;
553 }
554
555
556
557 static BOOL tcon_devtest(struct smbcli_state *cli,
558                          const char *myshare, const char *devtype,
559                          NTSTATUS expected_error)
560 {
561         BOOL status;
562         BOOL ret;
563         const char *password = lp_parm_string(-1, "torture", "password");
564
565         status = NT_STATUS_IS_OK(smbcli_tconX(cli, myshare, devtype, 
566                                                 password));
567
568         printf("Trying share %s with devtype %s\n", myshare, devtype);
569
570         if (NT_STATUS_IS_OK(expected_error)) {
571                 if (status) {
572                         ret = True;
573                 } else {
574                         printf("tconX to share %s with type %s "
575                                "should have succeeded but failed\n",
576                                myshare, devtype);
577                         ret = False;
578                 }
579                 smbcli_tdis(cli);
580         } else {
581                 if (status) {
582                         printf("tconx to share %s with type %s "
583                                "should have failed but succeeded\n",
584                                myshare, devtype);
585                         ret = False;
586                 } else {
587                         if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),
588                                             expected_error)) {
589                                 ret = True;
590                         } else {
591                                 printf("Returned unexpected error\n");
592                                 ret = False;
593                         }
594                 }
595         }
596         return ret;
597 }
598
599 /*
600  checks for correct tconX support
601  */
602 static BOOL run_tcon_devtype_test(void)
603 {
604         struct smbcli_state *cli1 = NULL;
605         NTSTATUS status;
606         BOOL ret = True;
607         const char *host = lp_parm_string(-1, "torture", "host");
608         const char *share = lp_parm_string(-1, "torture", "share");
609         
610         status = smbcli_full_connection(NULL,
611                                         &cli1, host, 
612                                         share, NULL,
613                                         cmdline_credentials, NULL);
614
615         if (!NT_STATUS_IS_OK(status)) {
616                 printf("could not open connection\n");
617                 return False;
618         }
619
620         if (!tcon_devtest(cli1, "IPC$", "A:", NT_STATUS_BAD_DEVICE_TYPE))
621                 ret = False;
622
623         if (!tcon_devtest(cli1, "IPC$", "?????", NT_STATUS_OK))
624                 ret = False;
625
626         if (!tcon_devtest(cli1, "IPC$", "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
627                 ret = False;
628
629         if (!tcon_devtest(cli1, "IPC$", "IPC", NT_STATUS_OK))
630                 ret = False;
631                         
632         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
633                 ret = False;
634
635         if (!tcon_devtest(cli1, share, "A:", NT_STATUS_OK))
636                 ret = False;
637
638         if (!tcon_devtest(cli1, share, "?????", NT_STATUS_OK))
639                 ret = False;
640
641         if (!tcon_devtest(cli1, share, "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
642                 ret = False;
643
644         if (!tcon_devtest(cli1, share, "IPC", NT_STATUS_BAD_DEVICE_TYPE))
645                 ret = False;
646                         
647         if (!tcon_devtest(cli1, share, "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
648                 ret = False;
649
650         talloc_free(cli1);
651
652         if (ret)
653                 printf("Passed tcondevtest\n");
654
655         return ret;
656 }
657
658
659 /*
660 test whether fnums and tids open on one VC are available on another (a major
661 security hole)
662 */
663 static BOOL run_fdpasstest(void)
664 {
665         struct smbcli_state *cli1, *cli2;
666         const char *fname = "\\fdpass.tst";
667         int fnum1, oldtid;
668         uint8_t buf[1024];
669
670         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
671                 return False;
672         }
673
674         printf("starting fdpasstest\n");
675
676         smbcli_unlink(cli1->tree, fname);
677
678         printf("Opening a file on connection 1\n");
679
680         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
681         if (fnum1 == -1) {
682                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
683                 return False;
684         }
685
686         printf("writing to file on connection 1\n");
687
688         if (smbcli_write(cli1->tree, fnum1, 0, "hello world\n", 0, 13) != 13) {
689                 printf("write failed (%s)\n", smbcli_errstr(cli1->tree));
690                 return False;
691         }
692
693         oldtid = cli2->tree->tid;
694         cli2->session->vuid = cli1->session->vuid;
695         cli2->tree->tid = cli1->tree->tid;
696         cli2->session->pid = cli1->session->pid;
697
698         printf("reading from file on connection 2\n");
699
700         if (smbcli_read(cli2->tree, fnum1, buf, 0, 13) == 13) {
701                 printf("read succeeded! nasty security hole [%s]\n",
702                        buf);
703                 return False;
704         }
705
706         smbcli_close(cli1->tree, fnum1);
707         smbcli_unlink(cli1->tree, fname);
708
709         cli2->tree->tid = oldtid;
710
711         torture_close_connection(cli1);
712         torture_close_connection(cli2);
713
714         printf("finished fdpasstest\n");
715         return True;
716 }
717
718
719 /*
720 test the timing of deferred open requests
721 */
722 static BOOL run_deferopen(struct smbcli_state *cli, int dummy)
723 {
724         const char *fname = "\\defer_open_test.dat";
725         int retries=4;
726         int i = 0;
727         BOOL correct = True;
728
729         if (retries <= 0) {
730                 printf("failed to connect\n");
731                 return False;
732         }
733
734         printf("Testing deferred open requests.\n");
735
736         while (i < 4) {
737                 int fnum = -1;
738
739                 do {
740                         struct timeval tv;
741                         tv = timeval_current();
742                         fnum = smbcli_nt_create_full(cli->tree, fname, 0, 
743                                                      SEC_RIGHTS_FILE_ALL,
744                                                      FILE_ATTRIBUTE_NORMAL, 
745                                                      NTCREATEX_SHARE_ACCESS_NONE,
746                                                      NTCREATEX_DISP_OPEN_IF, 0, 0);
747                         if (fnum != -1) {
748                                 break;
749                         }
750                         if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION)) {
751                                 double e = timeval_elapsed(&tv);
752                                 if (e < 0.5 || e > 1.5) {
753                                         fprintf(stderr,"Timing incorrect %.2f violation\n",
754                                                 e);
755                                 }
756                         }
757                 } while (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION));
758
759                 if (fnum == -1) {
760                         fprintf(stderr,"Failed to open %s, error=%s\n", fname, smbcli_errstr(cli->tree));
761                         return False;
762                 }
763
764                 printf("pid %u open %d\n", getpid(), i);
765
766                 sleep(10);
767                 i++;
768                 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum))) {
769                         fprintf(stderr,"Failed to close %s, error=%s\n", fname, smbcli_errstr(cli->tree));
770                         return False;
771                 }
772                 sleep(2);
773         }
774
775         if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
776                 /* All until the last unlink will fail with sharing violation. */
777                 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION)) {
778                         printf("unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
779                         correct = False;
780                 }
781         }
782
783         printf("deferred test finished\n");
784         if (!torture_close_connection(cli)) {
785                 correct = False;
786         }
787         return correct;
788 }
789
790 /*
791 test how many open files this server supports on the one socket
792 */
793 static BOOL run_maxfidtest(struct smbcli_state *cli, int dummy)
794 {
795 #define MAXFID_TEMPLATE "\\maxfid\\fid%d\\maxfid.%d.%d"
796         char *fname;
797         int fnums[0x11000], i;
798         int retries=4, maxfid;
799         BOOL correct = True;
800
801         if (retries <= 0) {
802                 printf("failed to connect\n");
803                 return False;
804         }
805
806         if (smbcli_deltree(cli->tree, "\\maxfid") == -1) {
807                 printf("Failed to deltree \\maxfid - %s\n",
808                        smbcli_errstr(cli->tree));
809                 return False;
810         }
811         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\maxfid"))) {
812                 printf("Failed to mkdir \\maxfid, error=%s\n", 
813                        smbcli_errstr(cli->tree));
814                 return False;
815         }
816
817         printf("Testing maximum number of open files\n");
818
819         for (i=0; i<0x11000; i++) {
820                 if (i % 1000 == 0) {
821                         asprintf(&fname, "\\maxfid\\fid%d", i/1000);
822                         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, fname))) {
823                                 printf("Failed to mkdir %s, error=%s\n", 
824                                        fname, smbcli_errstr(cli->tree));
825                                 return False;
826                         }
827                         free(fname);
828                 }
829                 asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid());
830                 if ((fnums[i] = smbcli_open(cli->tree, fname, 
831                                         O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) ==
832                     -1) {
833                         printf("open of %s failed (%s)\n", 
834                                fname, smbcli_errstr(cli->tree));
835                         printf("maximum fnum is %d\n", i);
836                         break;
837                 }
838                 free(fname);
839                 printf("%6d\r", i);
840         }
841         printf("%6d\n", i);
842         i--;
843
844         maxfid = i;
845
846         printf("cleaning up\n");
847         for (i=0;i<maxfid/2;i++) {
848                 asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid());
849                 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[i]))) {
850                         printf("Close of fnum %d failed - %s\n", fnums[i], smbcli_errstr(cli->tree));
851                 }
852                 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
853                         printf("unlink of %s failed (%s)\n", 
854                                fname, smbcli_errstr(cli->tree));
855                         correct = False;
856                 }
857                 free(fname);
858
859                 asprintf(&fname, MAXFID_TEMPLATE, (maxfid-i)/1000, maxfid-i,(int)getpid());
860                 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[maxfid-i]))) {
861                         printf("Close of fnum %d failed - %s\n", fnums[maxfid-i], smbcli_errstr(cli->tree));
862                 }
863                 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
864                         printf("unlink of %s failed (%s)\n", 
865                                fname, smbcli_errstr(cli->tree));
866                         correct = False;
867                 }
868                 free(fname);
869
870                 printf("%6d %6d\r", i, maxfid-i);
871         }
872         printf("%6d\n", 0);
873
874         if (smbcli_deltree(cli->tree, "\\maxfid") == -1) {
875                 printf("Failed to deltree \\maxfid - %s\n",
876                        smbcli_errstr(cli->tree));
877                 return False;
878         }
879
880         printf("maxfid test finished\n");
881         if (!torture_close_connection(cli)) {
882                 correct = False;
883         }
884         return correct;
885 #undef MAXFID_TEMPLATE
886 }
887
888 /* send smb negprot commands, not reading the response */
889 static BOOL run_negprot_nowait(void)
890 {
891         int i;
892         struct smbcli_state *cli, *cli2;
893         BOOL correct = True;
894
895         printf("starting negprot nowait test\n");
896
897         cli = open_nbt_connection();
898         if (!cli) {
899                 return False;
900         }
901
902         printf("Filling send buffer\n");
903
904         for (i=0;i<1000;i++) {
905                 struct smbcli_request *req;
906                 req = smb_raw_negotiate_send(cli->transport, PROTOCOL_NT1);
907                 smbcli_transport_process(cli->transport);
908                 if (req->state == SMBCLI_REQUEST_ERROR) {
909                         printf("Failed to fill pipe - %s\n", nt_errstr(req->status));
910                         torture_close_connection(cli);
911                         return correct;
912                 }
913         }
914
915         printf("Opening secondary connection\n");
916         if (!torture_open_connection(&cli2)) {
917                 return False;
918         }
919
920         if (!torture_close_connection(cli)) {
921                 correct = False;
922         }
923
924         if (!torture_close_connection(cli2)) {
925                 correct = False;
926         }
927
928         printf("finished negprot nowait test\n");
929
930         return correct;
931 }
932
933
934 /*
935   This checks how the getatr calls works
936 */
937 static BOOL run_attrtest(void)
938 {
939         struct smbcli_state *cli;
940         int fnum;
941         time_t t, t2;
942         const char *fname = "\\attrib123456789.tst";
943         BOOL correct = True;
944
945         printf("starting attrib test\n");
946
947         if (!torture_open_connection(&cli)) {
948                 return False;
949         }
950
951         smbcli_unlink(cli->tree, fname);
952         fnum = smbcli_open(cli->tree, fname, 
953                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
954         smbcli_close(cli->tree, fnum);
955
956         if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
957                 printf("getatr failed (%s)\n", smbcli_errstr(cli->tree));
958                 correct = False;
959         }
960
961         printf("New file time is %s", ctime(&t));
962
963         if (abs(t - time(NULL)) > 60*60*24*10) {
964                 printf("ERROR: SMBgetatr bug. time is %s",
965                        ctime(&t));
966                 t = time(NULL);
967                 correct = False;
968         }
969
970         t2 = t-60*60*24; /* 1 day ago */
971
972         printf("Setting file time to %s", ctime(&t2));
973
974         if (NT_STATUS_IS_ERR(smbcli_setatr(cli->tree, fname, 0, t2))) {
975                 printf("setatr failed (%s)\n", smbcli_errstr(cli->tree));
976                 correct = True;
977         }
978
979         if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
980                 printf("getatr failed (%s)\n", smbcli_errstr(cli->tree));
981                 correct = True;
982         }
983
984         printf("Retrieved file time as %s", ctime(&t));
985
986         if (t != t2) {
987                 printf("ERROR: getatr/setatr bug. times are\n%s",
988                        ctime(&t));
989                 printf("%s", ctime(&t2));
990                 correct = True;
991         }
992
993         smbcli_unlink(cli->tree, fname);
994
995         if (!torture_close_connection(cli)) {
996                 correct = False;
997         }
998
999         printf("attrib test finished\n");
1000
1001         return correct;
1002 }
1003
1004
1005 /*
1006   This checks a couple of trans2 calls
1007 */
1008 static BOOL run_trans2test(void)
1009 {
1010         struct smbcli_state *cli;
1011         int fnum;
1012         size_t size;
1013         time_t c_time, a_time, m_time, w_time, m_time2;
1014         const char *fname = "\\trans2.tst";
1015         const char *dname = "\\trans2";
1016         const char *fname2 = "\\trans2\\trans2.tst";
1017         const char *pname;
1018         BOOL correct = True;
1019
1020         printf("starting trans2 test\n");
1021
1022         if (!torture_open_connection(&cli)) {
1023                 return False;
1024         }
1025
1026         smbcli_unlink(cli->tree, fname);
1027
1028         printf("Testing qfileinfo\n");
1029         
1030         fnum = smbcli_open(cli->tree, fname, 
1031                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1032         if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, NULL, &size, &c_time, &a_time, &m_time,
1033                            NULL, NULL))) {
1034                 printf("ERROR: qfileinfo failed (%s)\n", smbcli_errstr(cli->tree));
1035                 correct = False;
1036         }
1037
1038         printf("Testing NAME_INFO\n");
1039
1040         if (NT_STATUS_IS_ERR(smbcli_qfilename(cli->tree, fnum, &pname))) {
1041                 printf("ERROR: qfilename failed (%s)\n", smbcli_errstr(cli->tree));
1042                 correct = False;
1043         }
1044
1045         if (!pname || strcmp(pname, fname)) {
1046                 printf("qfilename gave different name? [%s] [%s]\n",
1047                        fname, pname);
1048                 correct = False;
1049         }
1050
1051         smbcli_close(cli->tree, fnum);
1052         smbcli_unlink(cli->tree, fname);
1053
1054         fnum = smbcli_open(cli->tree, fname, 
1055                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1056         if (fnum == -1) {
1057                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
1058                 return False;
1059         }
1060         smbcli_close(cli->tree, fnum);
1061
1062         printf("Checking for sticky create times\n");
1063
1064         if (NT_STATUS_IS_ERR(smbcli_qpathinfo(cli->tree, fname, &c_time, &a_time, &m_time, &size, NULL))) {
1065                 printf("ERROR: qpathinfo failed (%s)\n", smbcli_errstr(cli->tree));
1066                 correct = False;
1067         } else {
1068                 if (c_time != m_time) {
1069                         printf("create time=%s", ctime(&c_time));
1070                         printf("modify time=%s", ctime(&m_time));
1071                         printf("This system appears to have sticky create times\n");
1072                 }
1073                 if (a_time % (60*60) == 0) {
1074                         printf("access time=%s", ctime(&a_time));
1075                         printf("This system appears to set a midnight access time\n");
1076                         correct = False;
1077                 }
1078
1079                 if (abs(m_time - time(NULL)) > 60*60*24*7) {
1080                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
1081                         correct = False;
1082                 }
1083         }
1084
1085
1086         smbcli_unlink(cli->tree, fname);
1087         fnum = smbcli_open(cli->tree, fname, 
1088                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1089         smbcli_close(cli->tree, fnum);
1090         if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, fname, &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
1091                 printf("ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
1092                 correct = False;
1093         } else {
1094                 if (w_time < 60*60*24*2) {
1095                         printf("write time=%s", ctime(&w_time));
1096                         printf("This system appears to set a initial 0 write time\n");
1097                         correct = False;
1098                 }
1099         }
1100
1101         smbcli_unlink(cli->tree, fname);
1102
1103
1104         /* check if the server updates the directory modification time
1105            when creating a new file */
1106         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) {
1107                 printf("ERROR: mkdir failed (%s)\n", smbcli_errstr(cli->tree));
1108                 correct = False;
1109         }
1110         sleep(3);
1111         if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
1112                 printf("ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
1113                 correct = False;
1114         }
1115
1116         fnum = smbcli_open(cli->tree, fname2, 
1117                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1118         smbcli_write(cli->tree, fnum,  0, &fnum, 0, sizeof(fnum));
1119         smbcli_close(cli->tree, fnum);
1120         if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time2, &w_time, &size, NULL, NULL))) {
1121                 printf("ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
1122                 correct = False;
1123         } else {
1124                 if (m_time2 == m_time) {
1125                         printf("This system does not update directory modification times\n");
1126                         correct = False;
1127                 }
1128         }
1129         smbcli_unlink(cli->tree, fname2);
1130         smbcli_rmdir(cli->tree, dname);
1131
1132         if (!torture_close_connection(cli)) {
1133                 correct = False;
1134         }
1135
1136         printf("trans2 test finished\n");
1137
1138         return correct;
1139 }
1140
1141
1142
1143 /* FIRST_DESIRED_ACCESS   0xf019f */
1144 #define FIRST_DESIRED_ACCESS   SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA|SEC_FILE_APPEND_DATA|\
1145                                SEC_FILE_READ_EA|                           /* 0xf */ \
1146                                SEC_FILE_WRITE_EA|SEC_FILE_READ_ATTRIBUTE|     /* 0x90 */ \
1147                                SEC_FILE_WRITE_ATTRIBUTE|                  /* 0x100 */ \
1148                                SEC_STD_DELETE|SEC_STD_READ_CONTROL|\
1149                                SEC_STD_WRITE_DAC|SEC_STD_WRITE_OWNER     /* 0xf0000 */
1150 /* SECOND_DESIRED_ACCESS  0xe0080 */
1151 #define SECOND_DESIRED_ACCESS  SEC_FILE_READ_ATTRIBUTE|                   /* 0x80 */ \
1152                                SEC_STD_READ_CONTROL|SEC_STD_WRITE_DAC|\
1153                                SEC_STD_WRITE_OWNER                      /* 0xe0000 */
1154
1155 #if 0
1156 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTE|                   /* 0x80 */ \
1157                                READ_CONTROL|WRITE_DAC|\
1158                                SEC_FILE_READ_DATA|\
1159                                WRITE_OWNER                      /* */
1160 #endif
1161
1162 /*
1163   Test ntcreate calls made by xcopy
1164  */
1165 static BOOL run_xcopy(void)
1166 {
1167         struct smbcli_state *cli1;
1168         const char *fname = "\\test.txt";
1169         BOOL correct = True;
1170         int fnum1, fnum2;
1171
1172         printf("starting xcopy test\n");
1173         
1174         if (!torture_open_connection(&cli1)) {
1175                 return False;
1176         }
1177         
1178         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1179                                       FIRST_DESIRED_ACCESS, 
1180                                       FILE_ATTRIBUTE_ARCHIVE,
1181                                       NTCREATEX_SHARE_ACCESS_NONE, 
1182                                       NTCREATEX_DISP_OVERWRITE_IF, 
1183                                       0x4044, 0);
1184
1185         if (fnum1 == -1) {
1186                 printf("First open failed - %s\n", smbcli_errstr(cli1->tree));
1187                 return False;
1188         }
1189
1190         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1191                                    SECOND_DESIRED_ACCESS, 0,
1192                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN, 
1193                                    0x200000, 0);
1194         if (fnum2 == -1) {
1195                 printf("second open failed - %s\n", smbcli_errstr(cli1->tree));
1196                 return False;
1197         }
1198         
1199         if (!torture_close_connection(cli1)) {
1200                 correct = False;
1201         }
1202         
1203         return correct;
1204 }
1205
1206
1207 /*
1208   see how many RPC pipes we can open at once
1209 */
1210 static BOOL run_pipe_number(void)
1211 {
1212         struct smbcli_state *cli1;
1213         const char *pipe_name = "\\WKSSVC";
1214         int fnum;
1215         int num_pipes = 0;
1216
1217         printf("starting pipenumber test\n");
1218         if (!torture_open_connection(&cli1)) {
1219                 return False;
1220         }
1221
1222         while(1) {
1223                 fnum = smbcli_nt_create_full(cli1->tree, pipe_name, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1224                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1225
1226                 if (fnum == -1) {
1227                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, smbcli_errstr(cli1->tree));
1228                         break;
1229                 }
1230                 num_pipes++;
1231                 printf("%d\r", num_pipes);
1232                 fflush(stdout);
1233         }
1234
1235         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
1236         torture_close_connection(cli1);
1237         return True;
1238 }
1239
1240
1241
1242
1243 /*
1244   open N connections to the server and just hold them open
1245   used for testing performance when there are N idle users
1246   already connected
1247  */
1248  static BOOL torture_holdcon(void)
1249 {
1250         int i;
1251         struct smbcli_state **cli;
1252         int num_dead = 0;
1253
1254         printf("Opening %d connections\n", torture_numops);
1255         
1256         cli = malloc_array_p(struct smbcli_state *, torture_numops);
1257
1258         for (i=0;i<torture_numops;i++) {
1259                 if (!torture_open_connection(&cli[i])) {
1260                         return False;
1261                 }
1262                 printf("opened %d connections\r", i);
1263                 fflush(stdout);
1264         }
1265
1266         printf("\nStarting pings\n");
1267
1268         while (1) {
1269                 for (i=0;i<torture_numops;i++) {
1270                         NTSTATUS status;
1271                         if (cli[i]) {
1272                                 status = smbcli_chkpath(cli[i]->tree, "\\");
1273                                 if (!NT_STATUS_IS_OK(status)) {
1274                                         printf("Connection %d is dead\n", i);
1275                                         cli[i] = NULL;
1276                                         num_dead++;
1277                                 }
1278                                 usleep(100);
1279                         }
1280                 }
1281
1282                 if (num_dead == torture_numops) {
1283                         printf("All connections dead - finishing\n");
1284                         break;
1285                 }
1286
1287                 printf(".");
1288                 fflush(stdout);
1289         }
1290
1291         return True;
1292 }
1293
1294 /*
1295   Try with a wrong vuid and check error message.
1296  */
1297
1298 static BOOL run_vuidtest(void)
1299 {
1300         struct smbcli_state *cli;
1301         const char *fname = "\\vuid.tst";
1302         int fnum;
1303         size_t size;
1304         time_t c_time, a_time, m_time;
1305         BOOL correct = True;
1306
1307         uint16_t orig_vuid;
1308         NTSTATUS result;
1309
1310         printf("starting vuid test\n");
1311
1312         if (!torture_open_connection(&cli)) {
1313                 return False;
1314         }
1315
1316         smbcli_unlink(cli->tree, fname);
1317
1318         fnum = smbcli_open(cli->tree, fname, 
1319                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1320
1321         orig_vuid = cli->session->vuid;
1322
1323         cli->session->vuid += 1234;
1324
1325         printf("Testing qfileinfo with wrong vuid\n");
1326         
1327         if (NT_STATUS_IS_OK(result = smbcli_qfileinfo(cli->tree, fnum, NULL,
1328                                                    &size, &c_time, &a_time,
1329                                                    &m_time, NULL, NULL))) {
1330                 printf("ERROR: qfileinfo passed with wrong vuid\n");
1331                 correct = False;
1332         }
1333
1334         if (!NT_STATUS_EQUAL(cli->transport->error.e.nt_status, 
1335                              NT_STATUS_DOS(ERRSRV, ERRbaduid)) &&
1336             !NT_STATUS_EQUAL(cli->transport->error.e.nt_status, 
1337                              NT_STATUS_INVALID_HANDLE)) {
1338                 printf("ERROR: qfileinfo should have returned DOS error "
1339                        "ERRSRV:ERRbaduid\n  but returned %s\n",
1340                        smbcli_errstr(cli->tree));
1341                 correct = False;
1342         }
1343
1344         cli->session->vuid -= 1234;
1345
1346         if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum))) {
1347                 printf("close failed (%s)\n", smbcli_errstr(cli->tree));
1348                 correct = False;
1349         }
1350
1351         smbcli_unlink(cli->tree, fname);
1352
1353         if (!torture_close_connection(cli)) {
1354                 correct = False;
1355         }
1356
1357         printf("vuid test finished\n");
1358
1359         return correct;
1360 }
1361
1362 /*
1363   Test open mode returns on read-only files.
1364  */
1365  static BOOL run_opentest(void)
1366 {
1367         static struct smbcli_state *cli1;
1368         static struct smbcli_state *cli2;
1369         const char *fname = "\\readonly.file";
1370         char *control_char_fname;
1371         int fnum1, fnum2;
1372         uint8_t buf[20];
1373         size_t fsize;
1374         BOOL correct = True;
1375         char *tmp_path;
1376         int failures = 0;
1377         int i;
1378
1379         printf("starting open test\n");
1380         
1381         if (!torture_open_connection(&cli1)) {
1382                 return False;
1383         }
1384         
1385         asprintf(&control_char_fname, "\\readonly.afile");
1386         for (i = 1; i <= 0x1f; i++) {
1387                 control_char_fname[10] = i;
1388                 fnum1 = smbcli_nt_create_full(cli1->tree, control_char_fname, 0, SEC_FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
1389                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1390                 
1391                 if (!check_error(__location__, cli1, ERRDOS, ERRinvalidname, 
1392                                 NT_STATUS_OBJECT_NAME_INVALID)) {
1393                         printf("Error code should be NT_STATUS_OBJECT_NAME_INVALID, was %s for file with %d char\n",
1394                                         smbcli_errstr(cli1->tree), i);
1395                         failures++;
1396                 }
1397
1398                 if (fnum1 != -1) {
1399                         smbcli_close(cli1->tree, fnum1);
1400                 }
1401                 smbcli_setatr(cli1->tree, control_char_fname, 0, 0);
1402                 smbcli_unlink(cli1->tree, control_char_fname);
1403         }
1404         free(control_char_fname);
1405
1406         if (!failures)
1407                 printf("Create file with control char names passed.\n");
1408
1409         smbcli_setatr(cli1->tree, fname, 0, 0);
1410         smbcli_unlink(cli1->tree, fname);
1411         
1412         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1413         if (fnum1 == -1) {
1414                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1415                 return False;
1416         }
1417
1418         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1419                 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
1420                 return False;
1421         }
1422         
1423         if (NT_STATUS_IS_ERR(smbcli_setatr(cli1->tree, fname, FILE_ATTRIBUTE_READONLY, 0))) {
1424                 printf("smbcli_setatr failed (%s)\n", smbcli_errstr(cli1->tree));
1425                 CHECK_MAX_FAILURES(error_test1);
1426                 return False;
1427         }
1428         
1429         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
1430         if (fnum1 == -1) {
1431                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1432                 CHECK_MAX_FAILURES(error_test1);
1433                 return False;
1434         }
1435         
1436         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
1437         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
1438         
1439         if (check_error(__location__, cli1, ERRDOS, ERRnoaccess, 
1440                         NT_STATUS_ACCESS_DENIED)) {
1441                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
1442         }
1443         
1444         printf("finished open test 1\n");
1445 error_test1:
1446         smbcli_close(cli1->tree, fnum1);
1447         
1448         /* Now try not readonly and ensure ERRbadshare is returned. */
1449         
1450         smbcli_setatr(cli1->tree, fname, 0, 0);
1451         
1452         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
1453         if (fnum1 == -1) {
1454                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1455                 return False;
1456         }
1457         
1458         /* This will fail - but the error should be ERRshare. */
1459         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
1460         
1461         if (check_error(__location__, cli1, ERRDOS, ERRbadshare, 
1462                         NT_STATUS_SHARING_VIOLATION)) {
1463                 printf("correct error code ERRDOS/ERRbadshare returned\n");
1464         }
1465         
1466         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1467                 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
1468                 return False;
1469         }
1470         
1471         smbcli_unlink(cli1->tree, fname);
1472         
1473         printf("finished open test 2\n");
1474         
1475         /* Test truncate open disposition on file opened for read. */
1476         
1477         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1478         if (fnum1 == -1) {
1479                 printf("(3) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1480                 return False;
1481         }
1482         
1483         /* write 20 bytes. */
1484         
1485         memset(buf, '\0', 20);
1486
1487         if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
1488                 printf("write failed (%s)\n", smbcli_errstr(cli1->tree));
1489                 correct = False;
1490         }
1491
1492         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1493                 printf("(3) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1494                 return False;
1495         }
1496         
1497         /* Ensure size == 20. */
1498         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1499                 printf("(3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
1500                 CHECK_MAX_FAILURES(error_test3);
1501                 return False;
1502         }
1503         
1504         if (fsize != 20) {
1505                 printf("(3) file size != 20\n");
1506                 CHECK_MAX_FAILURES(error_test3);
1507                 return False;
1508         }
1509
1510         /* Now test if we can truncate a file opened for readonly. */
1511         
1512         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY|O_TRUNC, DENY_NONE);
1513         if (fnum1 == -1) {
1514                 printf("(3) open (2) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1515                 CHECK_MAX_FAILURES(error_test3);
1516                 return False;
1517         }
1518         
1519         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1520                 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
1521                 return False;
1522         }
1523
1524         /* Ensure size == 0. */
1525         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1526                 printf("(3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
1527                 CHECK_MAX_FAILURES(error_test3);
1528                 return False;
1529         }
1530
1531         if (fsize != 0) {
1532                 printf("(3) file size != 0\n");
1533                 CHECK_MAX_FAILURES(error_test3);
1534                 return False;
1535         }
1536         printf("finished open test 3\n");
1537 error_test3:    
1538         smbcli_unlink(cli1->tree, fname);
1539
1540
1541         printf("testing ctemp\n");
1542         fnum1 = smbcli_ctemp(cli1->tree, "\\", &tmp_path);
1543         if (fnum1 == -1) {
1544                 printf("ctemp failed (%s)\n", smbcli_errstr(cli1->tree));
1545                 CHECK_MAX_FAILURES(error_test4);
1546                 return False;
1547         }
1548         printf("ctemp gave path %s\n", tmp_path);
1549         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1550                 printf("close of temp failed (%s)\n", smbcli_errstr(cli1->tree));
1551         }
1552         if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, tmp_path))) {
1553                 printf("unlink of temp failed (%s)\n", smbcli_errstr(cli1->tree));
1554         }
1555 error_test4:    
1556         /* Test the non-io opens... */
1557
1558         if (!torture_open_connection(&cli2)) {
1559                 return False;
1560         }
1561         
1562         smbcli_setatr(cli2->tree, fname, 0, 0);
1563         smbcli_unlink(cli2->tree, fname);
1564         
1565         printf("TEST #1 testing 2 non-io opens (no delete)\n");
1566         
1567         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1568                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1569
1570         if (fnum1 == -1) {
1571                 printf("test 1 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1572                 CHECK_MAX_FAILURES(error_test10);
1573                 return False;
1574         }
1575
1576         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1577                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1578         if (fnum2 == -1) {
1579                 printf("test 1 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1580                 CHECK_MAX_FAILURES(error_test10);
1581                 return False;
1582         }
1583
1584         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1585                 printf("test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1586                 return False;
1587         }
1588         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1589                 printf("test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1590                 return False;
1591         }
1592
1593         printf("non-io open test #1 passed.\n");
1594 error_test10:
1595         smbcli_unlink(cli1->tree, fname);
1596
1597         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
1598         
1599         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1600                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1601
1602         if (fnum1 == -1) {
1603                 printf("test 2 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1604                 CHECK_MAX_FAILURES(error_test20);
1605                 return False;
1606         }
1607
1608         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1609                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1610
1611         if (fnum2 == -1) {
1612                 printf("test 2 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1613                 CHECK_MAX_FAILURES(error_test20);
1614                 return False;
1615         }
1616
1617         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1618                 printf("test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1619                 return False;
1620         }
1621         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1622                 printf("test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1623                 return False;
1624         }
1625
1626         printf("non-io open test #2 passed.\n");
1627 error_test20:
1628         smbcli_unlink(cli1->tree, fname);
1629
1630         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
1631         
1632         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1633                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1634
1635         if (fnum1 == -1) {
1636                 printf("test 3 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1637                 CHECK_MAX_FAILURES(error_test30);
1638                 return False;
1639         }
1640
1641         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1642                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1643
1644         if (fnum2 == -1) {
1645                 printf("test 3 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1646                 CHECK_MAX_FAILURES(error_test30);
1647                 return False;
1648         }
1649
1650         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1651                 printf("test 3 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1652                 return False;
1653         }
1654         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1655                 printf("test 3 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1656                 return False;
1657         }
1658
1659         printf("non-io open test #3 passed.\n");
1660 error_test30:
1661         smbcli_unlink(cli1->tree, fname);
1662
1663         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
1664         
1665         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1666                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1667
1668         if (fnum1 == -1) {
1669                 printf("test 4 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1670                 CHECK_MAX_FAILURES(error_test40);
1671                 return False;
1672         }
1673
1674         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1675                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1676
1677         if (fnum2 != -1) {
1678                 printf("test 4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1679                 CHECK_MAX_FAILURES(error_test40);
1680                 return False;
1681         }
1682
1683         printf("test 4 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1684
1685         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1686                 printf("test 4 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1687                 return False;
1688         }
1689
1690         printf("non-io open test #4 passed.\n");
1691 error_test40:
1692         smbcli_unlink(cli1->tree, fname);
1693
1694         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
1695         
1696         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1697                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1698
1699         if (fnum1 == -1) {
1700                 printf("test 5 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1701                 CHECK_MAX_FAILURES(error_test50);
1702                 return False;
1703         }
1704
1705         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1706                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1707
1708         if (fnum2 == -1) {
1709                 printf("test 5 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1710                 CHECK_MAX_FAILURES(error_test50);
1711                 return False;
1712         }
1713
1714         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1715                 printf("test 5 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1716                 return False;
1717         }
1718
1719         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1720                 printf("test 5 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1721                 return False;
1722         }
1723
1724         printf("non-io open test #5 passed.\n");
1725 error_test50:
1726         printf("TEST #6 testing 1 non-io open, one io open\n");
1727         
1728         smbcli_unlink(cli1->tree, fname);
1729
1730         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1731                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1732
1733         if (fnum1 == -1) {
1734                 printf("test 6 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1735                 CHECK_MAX_FAILURES(error_test60);
1736                 return False;
1737         }
1738
1739         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1740                                    NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OPEN_IF, 0, 0);
1741
1742         if (fnum2 == -1) {
1743                 printf("test 6 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1744                 CHECK_MAX_FAILURES(error_test60);
1745                 return False;
1746         }
1747
1748         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1749                 printf("test 6 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1750                 return False;
1751         }
1752
1753         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1754                 printf("test 6 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1755                 return False;
1756         }
1757
1758         printf("non-io open test #6 passed.\n");
1759 error_test60:
1760         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
1761
1762         smbcli_unlink(cli1->tree, fname);
1763
1764         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1765                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1766
1767         if (fnum1 == -1) {
1768                 printf("test 7 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1769                 CHECK_MAX_FAILURES(error_test70);
1770                 return False;
1771         }
1772
1773         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1774                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1775
1776         if (fnum2 != -1) {
1777                 printf("test 7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1778                 CHECK_MAX_FAILURES(error_test70);
1779                 return False;
1780         }
1781
1782         printf("test 7 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1783
1784         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1785                 printf("test 7 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1786                 return False;
1787         }
1788
1789         printf("non-io open test #7 passed.\n");
1790
1791 error_test70:
1792
1793         printf("TEST #8 testing one normal open, followed by lock, followed by open with truncate\n");
1794
1795         smbcli_unlink(cli1->tree, fname);
1796
1797         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1798         if (fnum1 == -1) {
1799                 printf("(8) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1800                 return False;
1801         }
1802         
1803         /* write 20 bytes. */
1804         
1805         memset(buf, '\0', 20);
1806
1807         if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
1808                 printf("(8) write failed (%s)\n", smbcli_errstr(cli1->tree));
1809                 correct = False;
1810         }
1811
1812         /* Ensure size == 20. */
1813         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1814                 printf("(8) getatr (1) failed (%s)\n", smbcli_errstr(cli1->tree));
1815                 CHECK_MAX_FAILURES(error_test80);
1816                 return False;
1817         }
1818         
1819         if (fsize != 20) {
1820                 printf("(8) file size != 20\n");
1821                 CHECK_MAX_FAILURES(error_test80);
1822                 return False;
1823         }
1824
1825         /* Get an exclusive lock on the open file. */
1826         if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
1827                 printf("(8) lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
1828                 CHECK_MAX_FAILURES(error_test80);
1829                 return False;
1830         }
1831
1832         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
1833         if (fnum1 == -1) {
1834                 printf("(8) open (2) of %s with truncate failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1835                 return False;
1836         }
1837
1838         /* Ensure size == 0. */
1839         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1840                 printf("(8) getatr (2) failed (%s)\n", smbcli_errstr(cli1->tree));
1841                 CHECK_MAX_FAILURES(error_test80);
1842                 return False;
1843         }
1844         
1845         if (fsize != 0) {
1846                 printf("(8) file size != 0\n");
1847                 CHECK_MAX_FAILURES(error_test80);
1848                 return False;
1849         }
1850
1851         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1852                 printf("(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1853                 return False;
1854         }
1855         
1856         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
1857                 printf("(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1858                 return False;
1859         }
1860         
1861 error_test80:
1862
1863         printf("open test #8 passed.\n");
1864
1865         smbcli_unlink(cli1->tree, fname);
1866
1867         if (!torture_close_connection(cli1)) {
1868                 correct = False;
1869         }
1870         if (!torture_close_connection(cli2)) {
1871                 correct = False;
1872         }
1873         
1874         return correct;
1875 }
1876
1877
1878 /*
1879   sees what IOCTLs are supported
1880  */
1881 BOOL torture_ioctl_test(void)
1882 {
1883         struct smbcli_state *cli;
1884         uint16_t device, function;
1885         int fnum;
1886         const char *fname = "\\ioctl.dat";
1887         NTSTATUS status;
1888         union smb_ioctl parms;
1889         TALLOC_CTX *mem_ctx;
1890
1891         if (!torture_open_connection(&cli)) {
1892                 return False;
1893         }
1894
1895         mem_ctx = talloc_init("ioctl_test");
1896
1897         printf("starting ioctl test\n");
1898
1899         smbcli_unlink(cli->tree, fname);
1900
1901         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1902         if (fnum == -1) {
1903                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
1904                 return False;
1905         }
1906
1907         parms.ioctl.level = RAW_IOCTL_IOCTL;
1908         parms.ioctl.in.fnum = fnum;
1909         parms.ioctl.in.request = IOCTL_QUERY_JOB_INFO;
1910         status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
1911         printf("ioctl job info: %s\n", smbcli_errstr(cli->tree));
1912
1913         for (device=0;device<0x100;device++) {
1914                 printf("testing device=0x%x\n", device);
1915                 for (function=0;function<0x100;function++) {
1916                         parms.ioctl.in.request = (device << 16) | function;
1917                         status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
1918
1919                         if (NT_STATUS_IS_OK(status)) {
1920                                 printf("ioctl device=0x%x function=0x%x OK : %d bytes\n", 
1921                                         device, function, (int)parms.ioctl.out.blob.length);
1922                         }
1923                 }
1924         }
1925
1926         if (!torture_close_connection(cli)) {
1927                 return False;
1928         }
1929
1930         return True;
1931 }
1932
1933
1934 /*
1935   tries variants of chkpath
1936  */
1937 BOOL torture_chkpath_test(void)
1938 {
1939         struct smbcli_state *cli;
1940         int fnum;
1941         BOOL ret;
1942
1943         if (!torture_open_connection(&cli)) {
1944                 return False;
1945         }
1946
1947         printf("starting chkpath test\n");
1948
1949         printf("Testing valid and invalid paths\n");
1950
1951         /* cleanup from an old run */
1952         smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
1953         smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
1954         smbcli_rmdir(cli->tree, "\\chkpath.dir");
1955
1956         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir"))) {
1957                 printf("mkdir1 failed : %s\n", smbcli_errstr(cli->tree));
1958                 return False;
1959         }
1960
1961         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir\\dir2"))) {
1962                 printf("mkdir2 failed : %s\n", smbcli_errstr(cli->tree));
1963                 return False;
1964         }
1965
1966         fnum = smbcli_open(cli->tree, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1967         if (fnum == -1) {
1968                 printf("open1 failed (%s)\n", smbcli_errstr(cli->tree));
1969                 return False;
1970         }
1971         smbcli_close(cli->tree, fnum);
1972
1973         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir"))) {
1974                 printf("chkpath1 failed: %s\n", smbcli_errstr(cli->tree));
1975                 ret = False;
1976         }
1977
1978         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dir2"))) {
1979                 printf("chkpath2 failed: %s\n", smbcli_errstr(cli->tree));
1980                 ret = False;
1981         }
1982
1983         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\foo.txt"))) {
1984                 ret = check_error(__location__, cli, ERRDOS, ERRbadpath, 
1985                                   NT_STATUS_NOT_A_DIRECTORY);
1986         } else {
1987                 printf("* chkpath on a file should fail\n");
1988                 ret = False;
1989         }
1990
1991         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\bar.txt"))) {
1992                 ret = check_error(__location__, cli, ERRDOS, ERRbadpath, 
1993                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
1994         } else {
1995                 printf("* chkpath on a non existent file should fail\n");
1996                 ret = False;
1997         }
1998
1999         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dirxx\\bar.txt"))) {
2000                 ret = check_error(__location__, cli, ERRDOS, ERRbadpath, 
2001                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
2002         } else {
2003                 printf("* chkpath on a non existent component should fail\n");
2004                 ret = False;
2005         }
2006
2007         smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
2008         smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
2009         smbcli_rmdir(cli->tree, "\\chkpath.dir");
2010
2011         if (!torture_close_connection(cli)) {
2012                 return False;
2013         }
2014
2015         return ret;
2016 }
2017
2018
2019 static void sigcont(int sig)
2020 {
2021 }
2022
2023 double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result)
2024 {
2025         int i, status;
2026         volatile pid_t *child_status;
2027         volatile BOOL *child_status_out;
2028         int synccount;
2029         int tries = 8;
2030         double start_time_limit = 10 + (torture_nprocs * 1.5);
2031         char **unc_list = NULL;
2032         const char *p;
2033         int num_unc_names = 0;
2034         struct timeval tv;
2035
2036         *result = True;
2037
2038         synccount = 0;
2039
2040         signal(SIGCONT, sigcont);
2041
2042         child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*torture_nprocs);
2043         if (!child_status) {
2044                 printf("Failed to setup shared memory\n");
2045                 return -1;
2046         }
2047
2048         child_status_out = (volatile BOOL *)shm_setup(sizeof(BOOL)*torture_nprocs);
2049         if (!child_status_out) {
2050                 printf("Failed to setup result status shared memory\n");
2051                 return -1;
2052         }
2053
2054         p = lp_parm_string(-1, "torture", "unclist");
2055         if (p) {
2056                 unc_list = file_lines_load(p, &num_unc_names, NULL);
2057                 if (!unc_list || num_unc_names <= 0) {
2058                         printf("Failed to load unc names list from '%s'\n", p);
2059                         exit(1);
2060                 }
2061         }
2062
2063         for (i = 0; i < torture_nprocs; i++) {
2064                 child_status[i] = 0;
2065                 child_status_out[i] = True;
2066         }
2067
2068         tv = timeval_current();
2069
2070         for (i=0;i<torture_nprocs;i++) {
2071                 procnum = i;
2072                 if (fork() == 0) {
2073                         char *myname;
2074                         const char *hostname=NULL, *sharename;
2075
2076                         pid_t mypid = getpid();
2077                         srandom(((int)mypid) ^ ((int)time(NULL)));
2078
2079                         asprintf(&myname, "CLIENT%d", i);
2080                         lp_set_cmdline("netbios name", myname);
2081                         free(myname);
2082
2083
2084                         if (unc_list) {
2085                                 if (!smbcli_parse_unc(unc_list[i % num_unc_names],
2086                                                       NULL, &hostname, &sharename)) {
2087                                         printf("Failed to parse UNC name %s\n",
2088                                                unc_list[i % num_unc_names]);
2089                                         exit(1);
2090                                 }
2091                         }
2092
2093                         while (1) {
2094                                 if (hostname) {
2095                                         if (torture_open_connection_share(NULL,
2096                                                                           &current_cli,
2097                                                                           hostname, 
2098                                                                           sharename,
2099                                                                           NULL)) {
2100                                                 break;
2101                                         }
2102                                 } else if (torture_open_connection(&current_cli)) {
2103                                                 break;
2104                                 }
2105                                 if (tries-- == 0) {
2106                                         printf("pid %d failed to start\n", (int)getpid());
2107                                         _exit(1);
2108                                 }
2109                                 msleep(100);    
2110                         }
2111
2112                         child_status[i] = getpid();
2113
2114                         pause();
2115
2116                         if (child_status[i]) {
2117                                 printf("Child %d failed to start!\n", i);
2118                                 child_status_out[i] = 1;
2119                                 _exit(1);
2120                         }
2121
2122                         child_status_out[i] = fn(current_cli, i);
2123                         _exit(0);
2124                 }
2125         }
2126
2127         do {
2128                 synccount = 0;
2129                 for (i=0;i<torture_nprocs;i++) {
2130                         if (child_status[i]) synccount++;
2131                 }
2132                 if (synccount == torture_nprocs) break;
2133                 msleep(100);
2134         } while (timeval_elapsed(&tv) < start_time_limit);
2135
2136         if (synccount != torture_nprocs) {
2137                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
2138                 *result = False;
2139                 return timeval_elapsed(&tv);
2140         }
2141
2142         printf("Starting %d clients\n", torture_nprocs);
2143
2144         /* start the client load */
2145         tv = timeval_current();
2146         for (i=0;i<torture_nprocs;i++) {
2147                 child_status[i] = 0;
2148         }
2149
2150         printf("%d clients started\n", torture_nprocs);
2151
2152         kill(0, SIGCONT);
2153
2154         for (i=0;i<torture_nprocs;i++) {
2155                 int ret;
2156                 while ((ret=waitpid(0, &status, 0)) == -1 && errno == EINTR) /* noop */ ;
2157                 if (ret == -1 || WEXITSTATUS(status) != 0) {
2158                         *result = False;
2159                 }
2160         }
2161
2162         printf("\n");
2163         
2164         for (i=0;i<torture_nprocs;i++) {
2165                 if (!child_status_out[i]) {
2166                         *result = False;
2167                 }
2168         }
2169         return timeval_elapsed(&tv);
2170 }
2171
2172 #define FLAG_MULTIPROC 1
2173
2174 static struct {
2175         const char *name;
2176         BOOL (*fn)(void);
2177         BOOL (*multi_fn)(struct smbcli_state *, int );
2178 } torture_ops[] = {
2179         /* base tests */
2180         {"BASE-FDPASS", run_fdpasstest, 0},
2181         {"BASE-LOCK1",  torture_locktest1,  0},
2182         {"BASE-LOCK2",  torture_locktest2,  0},
2183         {"BASE-LOCK3",  torture_locktest3,  0},
2184         {"BASE-LOCK4",  torture_locktest4,  0},
2185         {"BASE-LOCK5",  torture_locktest5,  0},
2186         {"BASE-LOCK6",  torture_locktest6,  0},
2187         {"BASE-LOCK7",  torture_locktest7,  0},
2188         {"BASE-UNLINK", torture_unlinktest, 0},
2189         {"BASE-ATTR",   run_attrtest,   0},
2190         {"BASE-TRANS2", run_trans2test, 0},
2191         {"BASE-NEGNOWAIT", run_negprot_nowait, 0},
2192         {"BASE-DIR1",  torture_dirtest1, 0},
2193         {"BASE-DIR2",  torture_dirtest2, 0},
2194         {"BASE-DENY1",  torture_denytest1, 0},
2195         {"BASE-DENY2",  torture_denytest2, 0},
2196         {"BASE-DENY3",  torture_denytest3, 0},
2197         {"BASE-DENYDOS",  torture_denydos_sharing, 0},
2198         {"BASE-NTDENY1",  NULL, torture_ntdenytest1},
2199         {"BASE-NTDENY2",  torture_ntdenytest2, 0},
2200         {"BASE-TCON",  run_tcon_test, 0},
2201         {"BASE-TCONDEV",  run_tcon_devtype_test, 0},
2202         {"BASE-VUID", run_vuidtest, 0},
2203         {"BASE-RW1",  run_readwritetest, 0},
2204         {"BASE-OPEN", run_opentest, 0},
2205         {"BASE-DEFER_OPEN", NULL, run_deferopen},
2206         {"BASE-XCOPY", run_xcopy, 0},
2207         {"BASE-RENAME", torture_test_rename, 0},
2208         {"BASE-DELETE", torture_test_delete, 0},
2209         {"BASE-PROPERTIES", torture_test_properties, 0},
2210         {"BASE-MANGLE", torture_mangle, 0},
2211         {"BASE-OPENATTR", torture_openattrtest, 0},
2212         {"BASE-CHARSET", torture_charset, 0},
2213         {"BASE-CHKPATH",  torture_chkpath_test, 0},
2214         {"BASE-SECLEAK",  torture_sec_leak, 0},
2215         {"BASE-DISCONNECT",  torture_disconnect, 0},
2216         {"BASE-DELAYWRITE", torture_delay_write, 0},
2217
2218         /* benchmarking tests */
2219         {"BENCH-HOLDCON",  torture_holdcon, 0},
2220         {"BENCH-NBENCH",  torture_nbench, 0},
2221         {"BENCH-TORTURE", NULL, run_torture},
2222         {"BENCH-NBT",     torture_bench_nbt, 0},
2223         {"BENCH-WINS",    torture_bench_wins, 0},
2224         {"BENCH-RPC",     torture_bench_rpc, 0},
2225         {"BENCH-CLDAP",   torture_bench_cldap, 0},
2226
2227         /* RAW smb tests */
2228         {"RAW-QFSINFO", torture_raw_qfsinfo, 0},
2229         {"RAW-QFILEINFO", torture_raw_qfileinfo, 0},
2230         {"RAW-SFILEINFO", torture_raw_sfileinfo, 0},
2231         {"RAW-SFILEINFO-BUG", torture_raw_sfileinfo_bug, 0},
2232         {"RAW-SEARCH", torture_raw_search, 0},
2233         {"RAW-CLOSE", torture_raw_close, 0},
2234         {"RAW-OPEN", torture_raw_open, 0},
2235         {"RAW-MKDIR", torture_raw_mkdir, 0},
2236         {"RAW-OPLOCK", torture_raw_oplock, 0},
2237         {"RAW-NOTIFY", torture_raw_notify, 0},
2238         {"RAW-MUX", torture_raw_mux, 0},
2239         {"RAW-IOCTL", torture_raw_ioctl, 0},
2240         {"RAW-CHKPATH", torture_raw_chkpath, 0},
2241         {"RAW-UNLINK", torture_raw_unlink, 0},
2242         {"RAW-READ", torture_raw_read, 0},
2243         {"RAW-WRITE", torture_raw_write, 0},
2244         {"RAW-LOCK", torture_raw_lock, 0},
2245         {"RAW-CONTEXT", torture_raw_context, 0},
2246         {"RAW-RENAME", torture_raw_rename, 0},
2247         {"RAW-SEEK", torture_raw_seek, 0},
2248         {"RAW-EAS", torture_raw_eas, 0},
2249         {"RAW-EAMAX", torture_max_eas, 0},
2250         {"RAW-STREAMS", torture_raw_streams, 0},
2251         {"RAW-ACLS", torture_raw_acls, 0},
2252         {"RAW-RAP", torture_raw_rap, 0},
2253         {"RAW-COMPOSITE", torture_raw_composite, 0},
2254
2255         /* SMB2 tests */
2256         {"SMB2-CONNECT", torture_smb2_connect, 0},
2257         {"SMB2-SCAN", torture_smb2_scan, 0},
2258         {"SMB2-SCANGETINFO", torture_smb2_getinfo_scan, 0},
2259         {"SMB2-SCANSETINFO", torture_smb2_setinfo_scan, 0},
2260         {"SMB2-SCANFIND", torture_smb2_find_scan, 0},
2261         {"SMB2-GETINFO", torture_smb2_getinfo, 0},
2262         {"SMB2-SETINFO", torture_smb2_setinfo, 0},
2263         {"SMB2-FIND", torture_smb2_find, 0},
2264
2265         /* protocol scanners */
2266         {"SCAN-TRANS2", torture_trans2_scan, 0},
2267         {"SCAN-NTTRANS", torture_nttrans_scan, 0},
2268         {"SCAN-ALIASES", torture_trans2_aliases, 0},
2269         {"SCAN-SMB", torture_smb_scan, 0},
2270         {"SCAN-MAXFID", NULL, run_maxfidtest},
2271         {"SCAN-UTABLE", torture_utable, 0},
2272         {"SCAN-CASETABLE", torture_casetable, 0},
2273         {"SCAN-PIPE_NUMBER", run_pipe_number, 0},
2274         {"SCAN-IOCTL",  torture_ioctl_test, 0},
2275         {"SCAN-RAP",  torture_rap_scan, 0},
2276
2277         /* rpc testers */
2278         {"RPC-LSA", torture_rpc_lsa, 0},
2279         {"RPC-SECRETS", torture_rpc_lsa_secrets, 0},
2280         {"RPC-ECHO", torture_rpc_echo, 0},
2281         {"RPC-DFS", torture_rpc_dfs, 0},
2282         {"RPC-SPOOLSS", torture_rpc_spoolss, 0},
2283         {"RPC-SAMR", torture_rpc_samr, 0},
2284         {"RPC-UNIXINFO", torture_rpc_unixinfo, 0},
2285         {"RPC-NETLOGON", torture_rpc_netlogon, 0},
2286         {"RPC-SAMLOGON", torture_rpc_samlogon, 0},
2287         {"RPC-SAMSYNC", torture_rpc_samsync, 0},
2288         {"RPC-SCHANNEL", torture_rpc_schannel, 0},
2289         {"RPC-WKSSVC", torture_rpc_wkssvc, 0},
2290         {"RPC-SRVSVC", torture_rpc_srvsvc, 0},
2291         {"RPC-SVCCTL", torture_rpc_svcctl, 0},
2292         {"RPC-ATSVC", torture_rpc_atsvc, 0},
2293         {"RPC-EVENTLOG", torture_rpc_eventlog, 0},
2294         {"RPC-EPMAPPER", torture_rpc_epmapper, 0},
2295         {"RPC-WINREG", torture_rpc_winreg, 0},
2296         {"RPC-INITSHUTDOWN", torture_rpc_initshutdown, 0},
2297         {"RPC-OXIDRESOLVE", torture_rpc_oxidresolve, 0},
2298         {"RPC-REMACT", torture_rpc_remact, 0},
2299         {"RPC-MGMT", torture_rpc_mgmt, 0},
2300         {"RPC-SCANNER", torture_rpc_scanner, 0},
2301         {"RPC-AUTOIDL", torture_rpc_autoidl, 0},
2302         {"RPC-COUNTCALLS", torture_rpc_countcalls, 0},
2303         {"RPC-MULTIBIND", torture_multi_bind, 0},
2304         {"RPC-DRSUAPI", torture_rpc_drsuapi, 0},
2305         {"RPC-CRACKNAMES", torture_rpc_drsuapi_cracknames, 0},
2306         {"RPC-ROT", torture_rpc_rot, 0},
2307         {"RPC-DSSETUP", torture_rpc_dssetup, 0},
2308         {"RPC-ALTERCONTEXT", torture_rpc_alter_context, 0},
2309         {"RPC-JOIN", torture_rpc_join, 0},
2310         {"RPC-DSSYNC", torture_rpc_dssync, 0},
2311
2312         /* local (no server) testers */
2313         {"LOCAL-NTLMSSP", torture_ntlmssp_self_check, 0},
2314         {"LOCAL-ICONV", torture_local_iconv, 0},
2315         {"LOCAL-TALLOC", torture_local_talloc, 0},
2316         {"LOCAL-MESSAGING", torture_local_messaging, 0},
2317         {"LOCAL-IRPC",  torture_local_irpc, 0},
2318         {"LOCAL-BINDING", torture_local_binding_string, 0},
2319         {"LOCAL-STRLIST", torture_local_util_strlist, 0},
2320         {"LOCAL-FILE", torture_local_util_file, 0},
2321         {"LOCAL-IDTREE", torture_local_idtree, 0},
2322         {"LOCAL-SOCKET", torture_local_socket, 0},
2323         {"LOCAL-PAC", torture_pac, 0},
2324         {"LOCAL-REGISTRY", torture_registry, 0},
2325         {"LOCAL-RESOLVE", torture_local_resolve, 0},
2326         {"LOCAL-SDDL", torture_local_sddl, 0},
2327
2328         /* COM (Component Object Model) testers */
2329         {"COM-SIMPLE", torture_com_simple, 0 },
2330
2331         /* ldap testers */
2332         {"LDAP-BASIC", torture_ldap_basic, 0},
2333         {"LDAP-CLDAP", torture_cldap, 0},
2334
2335         /* nbt tests */
2336         {"NBT-REGISTER", torture_nbt_register, 0},
2337         {"NBT-WINS", torture_nbt_wins, 0},
2338         {"NBT-DGRAM", torture_nbt_dgram, 0},
2339         {"NBT-WINSREPLICATION", torture_nbt_winsreplication, 0},
2340         
2341         /* libnet tests */
2342         {"NET-USERINFO", torture_userinfo, 0},
2343         {"NET-USERADD", torture_useradd, 0},
2344         {"NET-USERDEL", torture_userdel, 0},
2345         {"NET-USERMOD", torture_usermod, 0},
2346         {"NET-DOMOPEN", torture_domainopen, 0},
2347         {"NET-API-LOOKUP", torture_lookup, 0},
2348         {"NET-API-LOOKUPHOST", torture_lookup_host, 0},
2349         {"NET-API-LOOKUPPDC", torture_lookup_pdc, 0},
2350         {"NET-API-CREATEUSER", torture_createuser, 0},
2351         {"NET-API-RPCCONNECT", torture_rpc_connect, 0},
2352         {"NET-API-LISTSHARES", torture_listshares, 0},
2353         {"NET-API-DELSHARE", torture_delshare, 0},
2354
2355         {NULL, NULL, 0}};
2356
2357
2358
2359 /****************************************************************************
2360 run a specified test or "ALL"
2361 ****************************************************************************/
2362 static BOOL run_test(const char *name)
2363 {
2364         BOOL ret = True;
2365         int i;
2366         BOOL matched = False;
2367
2368         if (strequal(name,"ALL")) {
2369                 for (i=0;torture_ops[i].name;i++) {
2370                         if (!run_test(torture_ops[i].name)) {
2371                                 ret = False;
2372                         }
2373                 }
2374                 return ret;
2375         }
2376
2377         for (i=0;torture_ops[i].name;i++) {
2378                 if (gen_fnmatch(name, torture_ops[i].name) == 0) {
2379                         double t;
2380                         matched = True;
2381                         init_iconv();
2382                         printf("Running %s\n", torture_ops[i].name);
2383                         if (torture_ops[i].multi_fn) {
2384                                 BOOL result = False;
2385                                 t = torture_create_procs(torture_ops[i].multi_fn, 
2386                                                          &result);
2387                                 if (!result) { 
2388                                         ret = False;
2389                                         printf("TEST %s FAILED!\n", torture_ops[i].name);
2390                                 }
2391                                          
2392                         } else {
2393                                 struct timeval tv = timeval_current();
2394                                 if (!torture_ops[i].fn()) {
2395                                         ret = False;
2396                                         printf("TEST %s FAILED!\n", torture_ops[i].name);
2397                                 }
2398                                 t = timeval_elapsed(&tv);
2399                         }
2400                         printf("%s took %g secs\n\n", torture_ops[i].name, t);
2401                 }
2402         }
2403
2404         if (!matched) {
2405                 printf("Unknown torture operation '%s'\n", name);
2406         }
2407
2408         return ret;
2409 }
2410
2411
2412 static void parse_dns(const char *dns)
2413 {
2414         char *userdn, *basedn, *secret;
2415         char *p, *d;
2416
2417         /* retrievieng the userdn */
2418         p = strchr_m(dns, '#');
2419         if (!p) {
2420                 lp_set_cmdline("torture:ldap_userdn", "");
2421                 lp_set_cmdline("torture:ldap_basedn", "");
2422                 lp_set_cmdline("torture:ldap_secret", "");
2423                 return;
2424         }
2425         userdn = strndup(dns, p - dns);
2426         lp_set_cmdline("torture:ldap_userdn", userdn);
2427
2428         /* retrieve the basedn */
2429         d = p + 1;
2430         p = strchr_m(d, '#');
2431         if (!p) {
2432                 lp_set_cmdline("torture:ldap_basedn", "");
2433                 lp_set_cmdline("torture:ldap_secret", "");
2434                 return;
2435         }
2436         basedn = strndup(d, p - d);
2437         lp_set_cmdline("torture:ldap_basedn", basedn);
2438
2439         /* retrieve the secret */
2440         p = p + 1;
2441         if (!p) {
2442                 lp_set_cmdline("torture:ldap_secret", "");
2443                 return;
2444         }
2445         secret = strdup(p);
2446         lp_set_cmdline("torture:ldap_secret", secret);
2447
2448         printf ("%s - %s - %s\n", userdn, basedn, secret);
2449
2450 }
2451
2452 static void usage(poptContext pc)
2453 {
2454         int i;
2455         int perline = 5;
2456
2457         poptPrintUsage(pc, stdout, 0);
2458         printf("\n");
2459
2460         printf("The binding format is:\n\n");
2461
2462         printf("  TRANSPORT:host[flags]\n\n");
2463
2464         printf("  where TRANSPORT is either ncacn_np for SMB or ncacn_ip_tcp for RPC/TCP\n\n");
2465
2466         printf("  'host' is an IP or hostname or netbios name. If the binding string\n");
2467         printf("  identifies the server side of an endpoint, 'host' may be an empty\n");
2468         printf("  string.\n\n");
2469
2470         printf("  'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
2471         printf("  a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
2472         printf("  will be auto-determined.\n\n");
2473
2474         printf("  other recognised flags are:\n\n");
2475
2476         printf("    sign : enable ntlmssp signing\n");
2477         printf("    seal : enable ntlmssp sealing\n");
2478         printf("    connect : enable rpc connect level auth (auth, but no sign or seal)\n");
2479         printf("    validate: enable the NDR validator\n");
2480         printf("    print: enable debugging of the packets\n");
2481         printf("    bigendian: use bigendian RPC\n");
2482         printf("    padcheck: check reply data for non-zero pad bytes\n\n");
2483
2484         printf("  For example, these all connect to the samr pipe:\n\n");
2485
2486         printf("    ncacn_np:myserver\n");
2487         printf("    ncacn_np:myserver[samr]\n");
2488         printf("    ncacn_np:myserver[\\pipe\\samr]\n");
2489         printf("    ncacn_np:myserver[/pipe/samr]\n");
2490         printf("    ncacn_np:myserver[samr,sign,print]\n");
2491         printf("    ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
2492         printf("    ncacn_np:myserver[/pipe/samr,seal,validate]\n");
2493         printf("    ncacn_np:\n");
2494         printf("    ncacn_np:[/pipe/samr]\n\n");
2495
2496         printf("    ncacn_ip_tcp:myserver\n");
2497         printf("    ncacn_ip_tcp:myserver[1024]\n");
2498         printf("    ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
2499
2500         printf("The unc format is:\n\n");
2501
2502         printf("    //server/share\n\n");
2503
2504         printf("tests are:");
2505         for (i=0;torture_ops[i].name;i++) {
2506                 if ((i%perline)==0) {
2507                         printf("\n");
2508                 }
2509                 printf("%s ", torture_ops[i].name);
2510         }
2511         printf("\n\n");
2512
2513         printf("default test is ALL\n");
2514
2515         exit(1);
2516 }
2517
2518 static BOOL is_binding_string(const char *binding_string)
2519 {
2520         TALLOC_CTX *mem_ctx = talloc_init("is_binding_string");
2521         struct dcerpc_binding *binding_struct;
2522         NTSTATUS status;
2523         
2524         status = dcerpc_parse_binding(mem_ctx, binding_string, &binding_struct);
2525
2526         talloc_free(mem_ctx);
2527         return NT_STATUS_IS_OK(status);
2528 }
2529
2530 static void max_runtime_handler(int sig)
2531 {
2532         DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
2533         exit(1);
2534 }
2535
2536 /****************************************************************************
2537   main program
2538 ****************************************************************************/
2539  int main(int argc,char *argv[])
2540 {
2541         int opt, i;
2542         char *p;
2543         BOOL correct = True;
2544         int max_runtime=0;
2545         int argc_new;
2546         char **argv_new;
2547         poptContext pc;
2548         enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS,OPT_DANGEROUS};
2549         struct poptOption long_options[] = {
2550                 POPT_AUTOHELP
2551                 {"smb-ports",   'p', POPT_ARG_STRING, NULL,             0,      "SMB ports",    NULL},
2552                 {"seed",          0, POPT_ARG_INT,  &torture_seed,      0,      "seed",         NULL},
2553                 {"num-progs",     0, POPT_ARG_INT,  &torture_nprocs,    0,      "num progs",    NULL},
2554                 {"num-ops",       0, POPT_ARG_INT,  &torture_numops,    0,      "num ops",      NULL},
2555                 {"entries",       0, POPT_ARG_INT,  &torture_entries,   0,      "entries",      NULL},
2556                 {"use-oplocks", 'L', POPT_ARG_NONE, &use_oplocks,       0,      "use oplocks",  NULL},
2557                 {"show-all",      0, POPT_ARG_NONE, &torture_showall,   0,      "show all",     NULL},
2558                 {"loadfile",      0, POPT_ARG_STRING,   NULL,   OPT_LOADFILE,   "loadfile",     NULL},
2559                 {"unclist",       0, POPT_ARG_STRING,   NULL,   OPT_UNCLIST,    "unclist",      NULL},
2560                 {"timelimit",   't', POPT_ARG_STRING,   NULL,   OPT_TIMELIMIT,  "timelimit",    NULL},
2561                 {"failures",    'f', POPT_ARG_INT,  &torture_failures,  0,      "failures",     NULL},
2562                 {"parse-dns",   'D', POPT_ARG_STRING,   NULL,   OPT_DNS,        "parse-dns",    NULL},
2563                 {"dangerous",   'X', POPT_ARG_NONE,     NULL,   OPT_DANGEROUS,  "dangerous",    NULL},
2564                 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0, 
2565                  "set maximum time for smbtorture to live", "seconds"},
2566                 POPT_COMMON_SAMBA
2567                 POPT_COMMON_CONNECTION
2568                 POPT_COMMON_CREDENTIALS
2569                 POPT_COMMON_VERSION
2570                 POPT_TABLEEND
2571         };
2572
2573 #ifdef HAVE_SETBUFFER
2574         setbuffer(stdout, NULL, 0);
2575 #endif
2576
2577         pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options, 
2578                             POPT_CONTEXT_KEEP_FIRST);
2579
2580         poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
2581
2582         while((opt = poptGetNextOpt(pc)) != -1) {
2583                 switch (opt) {
2584                 case OPT_LOADFILE:
2585                         lp_set_cmdline("torture:loadfile", poptGetOptArg(pc));
2586                         break;
2587                 case OPT_UNCLIST:
2588                         lp_set_cmdline("torture:unclist", poptGetOptArg(pc));
2589                         break;
2590                 case OPT_TIMELIMIT:
2591                         lp_set_cmdline("torture:timelimit", poptGetOptArg(pc));
2592                         break;
2593                 case OPT_DNS:
2594                         parse_dns(poptGetOptArg(pc));
2595                         break;
2596                 case OPT_DANGEROUS:
2597                         lp_set_cmdline("torture:dangerous", "Yes");
2598                         break;
2599                 default:
2600                         d_printf("Invalid option %s: %s\n", 
2601                                  poptBadOption(pc, 0), poptStrerror(opt));
2602                         usage(pc);
2603                         exit(1);
2604                 }
2605         }
2606
2607         if (max_runtime) {
2608                 /* this will only work if nobody else uses alarm(),
2609                    which means it won't work for some tests, but we
2610                    can't use the event context method we use for smbd
2611                    as so many tests create their own event
2612                    context. This will at least catch most cases. */
2613                 signal(SIGALRM, max_runtime_handler);
2614                 alarm(max_runtime);
2615         }
2616
2617         smbtorture_init_subsystems;
2618
2619
2620         if (torture_seed == 0) {
2621                 torture_seed = time(NULL);
2622         } 
2623         printf("Using seed %d\n", torture_seed);
2624         srandom(torture_seed);
2625
2626         argv_new = discard_const_p(char *, poptGetArgs(pc));
2627
2628         argc_new = argc;
2629         for (i=0; i<argc; i++) {
2630                 if (argv_new[i] == NULL) {
2631                         argc_new = i;
2632                         break;
2633                 }
2634         }
2635
2636         if (argc_new < 3) {
2637                 usage(pc);
2638                 exit(1);
2639         }
2640
2641         for(p = argv_new[1]; *p; p++) {
2642                 if(*p == '\\')
2643                         *p = '/';
2644         }
2645
2646         /* see if its a RPC transport specifier */
2647         if (is_binding_string(argv_new[1])) {
2648                 lp_set_cmdline("torture:binding", argv_new[1]);
2649         } else {
2650                 char *binding = NULL;
2651                 const char *host = NULL, *share = NULL;
2652
2653                 if (!smbcli_parse_unc(argv_new[1], NULL, &host, &share)) {
2654                         d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", argv_new[1]);
2655                         usage(pc);
2656                 }
2657
2658                 lp_set_cmdline("torture:host", host);
2659                 lp_set_cmdline("torture:share", share);
2660                 asprintf(&binding, "ncacn_np:%s", host);
2661                 lp_set_cmdline("torture:binding", binding);
2662         }
2663
2664         if (argc_new == 0) {
2665                 printf("You must specify a test to run, or 'ALL'\n");
2666         } else {
2667                 for (i=2;i<argc_new;i++) {
2668                         if (!run_test(argv_new[i])) {
2669                                 correct = False;
2670                         }
2671                 }
2672         }
2673
2674         if (correct) {
2675                 return(0);
2676         } else {
2677                 return(1);
2678         }
2679 }