r3016: - converted the events code to talloc
[samba.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
23 int torture_nprocs=4;
24 int torture_numops=100;
25 int torture_entries=1000;
26 int torture_failures=1;
27 static int procnum; /* records process count number when forking */
28 static struct smbcli_state *current_cli;
29 static BOOL use_oplocks;
30 static BOOL use_level_II_oplocks;
31 static BOOL use_kerberos;
32
33 BOOL torture_showall = False;
34
35 #define CHECK_MAX_FAILURES(label) do { if (++failures >= torture_failures) goto label; } while (0)
36
37 static struct smbcli_state *open_nbt_connection(void)
38 {
39         struct nmb_name called, calling;
40         struct smbcli_state *cli;
41         const char *host = lp_parm_string(-1, "torture", "host");
42
43         make_nmb_name(&calling, lp_netbios_name(), 0x0);
44         choose_called_name(&called, host, 0x20);
45
46         cli = smbcli_state_init(NULL);
47         if (!cli) {
48                 printf("Failed initialize smbcli_struct to connect with %s\n", host);
49                 return NULL;
50         }
51
52         if (!smbcli_socket_connect(cli, host)) {
53                 printf("Failed to connect with %s\n", host);
54                 return cli;
55         }
56
57         cli->transport->socket->timeout = 120000; /* set a really long timeout (2 minutes) */
58
59         if (!smbcli_transport_establish(cli, &calling, &called)) {
60                 /*
61                  * Well, that failed, try *SMBSERVER ... 
62                  * However, we must reconnect as well ...
63                  */
64                 if (!smbcli_socket_connect(cli, host)) {
65                         printf("Failed to connect with %s\n", host);
66                         return False;
67                 }
68
69                 make_nmb_name(&called, "*SMBSERVER", 0x20);
70                 if (!smbcli_transport_establish(cli, &calling, &called)) {
71                         printf("%s rejected the session\n",host);
72                         printf("We tried with a called name of %s & %s\n",
73                                 host, "*SMBSERVER");
74                         smbcli_shutdown(cli);
75                         return NULL;
76                 }
77         }
78
79         return cli;
80 }
81
82 BOOL torture_open_connection_share(struct smbcli_state **c, 
83                                    const char *hostname, 
84                                    const char *sharename)
85 {
86         BOOL retry;
87         int flags = 0;
88         NTSTATUS status;
89         const char *username = lp_parm_string(-1, "torture", "username");
90         const char *userdomain = lp_parm_string(-1, "torture", "userdomain");
91         const char *password = lp_parm_string(-1, "torture", "password");
92
93         if (use_kerberos)
94                 flags |= SMBCLI_FULL_CONNECTION_USE_KERBEROS;
95
96         status = smbcli_full_connection(NULL,
97                                         c, lp_netbios_name(),
98                                         hostname, NULL, 
99                                         sharename, "?????", 
100                                         username, username[0]?userdomain:"",
101                                         password, flags, &retry);
102         if (!NT_STATUS_IS_OK(status)) {
103                 printf("Failed to open connection - %s\n", nt_errstr(status));
104                 return False;
105         }
106
107         (*c)->transport->options.use_oplocks = use_oplocks;
108         (*c)->transport->options.use_level2_oplocks = use_level_II_oplocks;
109         (*c)->transport->socket->timeout = 120000;
110
111         return True;
112 }
113
114 BOOL torture_open_connection(struct smbcli_state **c)
115 {
116         const char *host = lp_parm_string(-1, "torture", "host");
117         const char *share = lp_parm_string(-1, "torture", "share");
118
119         return torture_open_connection_share(c, host, share);
120 }
121
122
123
124 BOOL torture_close_connection(struct smbcli_state *c)
125 {
126         BOOL ret = True;
127         if (!c) return True;
128         if (NT_STATUS_IS_ERR(smbcli_tdis(c))) {
129                 printf("tdis failed (%s)\n", smbcli_errstr(c->tree));
130                 ret = False;
131         }
132         smbcli_shutdown(c);
133         return ret;
134 }
135
136
137 /* open a rpc connection to the chosen binding string */
138 NTSTATUS torture_rpc_connection(struct dcerpc_pipe **p, 
139                                 const char *pipe_name,
140                                 const char *pipe_uuid, 
141                                 uint32_t pipe_version)
142 {
143         NTSTATUS status;
144         const char *binding = lp_parm_string(-1, "torture", "binding");
145
146         if (!binding) {
147                 printf("You must specify a ncacn binding string\n");
148                 return NT_STATUS_INVALID_PARAMETER;
149         }
150
151         status = dcerpc_pipe_connect(p, binding, pipe_uuid, pipe_version,
152                                      lp_parm_string(-1, "torture", "userdomain"), 
153                                      lp_parm_string(-1, "torture", "username"),
154                                      lp_parm_string(-1, "torture", "password"));
155  
156         return status;
157 }
158
159 /* open a rpc connection to a specific transport */
160 NTSTATUS torture_rpc_connection_transport(struct dcerpc_pipe **p, 
161                                           const char *pipe_name,
162                                           const char *pipe_uuid, 
163                                           uint32_t pipe_version,
164                                           enum dcerpc_transport_t transport)
165 {
166         NTSTATUS status;
167         const char *binding = lp_parm_string(-1, "torture", "binding");
168         struct dcerpc_binding b;
169         TALLOC_CTX *mem_ctx = talloc_init("torture_rpc_connection_smb");
170
171         if (!binding) {
172                 printf("You must specify a ncacn binding string\n");
173                 return NT_STATUS_INVALID_PARAMETER;
174         }
175
176         status = dcerpc_parse_binding(mem_ctx, binding, &b);
177         if (!NT_STATUS_IS_OK(status)) {
178                 DEBUG(0,("Failed to parse dcerpc binding '%s'\n", binding));
179                 talloc_destroy(mem_ctx);
180                 return status;
181         }
182
183         b.transport = transport;
184
185         status = dcerpc_pipe_connect_b(p, &b, pipe_uuid, pipe_version,
186                                        lp_parm_string(-1, "torture", "userdomain"), 
187                                        lp_parm_string(-1, "torture", "username"),
188                                        lp_parm_string(-1, "torture", "password"));
189  
190         return status;
191 }
192
193 /* close a rpc connection to a named pipe */
194 NTSTATUS torture_rpc_close(struct dcerpc_pipe *p)
195 {
196         dcerpc_pipe_close(p);
197         return NT_STATUS_OK;
198 }
199
200
201 /* check if the server produced the expected error code */
202 BOOL check_error(const char *location, struct smbcli_state *c, 
203                  uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
204 {
205         if (smbcli_is_dos_error(c->tree)) {
206                 uint8_t class;
207                 uint32_t num;
208
209                 /* Check DOS error */
210
211                 smbcli_dos_error(c, &class, &num);
212
213                 if (eclass != class || ecode != num) {
214                         printf("unexpected error code class=%d code=%d\n", 
215                                (int)class, (int)num);
216                         printf(" expected %d/%d %s (at %s)\n", 
217                                (int)eclass, (int)ecode, nt_errstr(nterr), location);
218                         return False;
219                 }
220
221         } else {
222                 NTSTATUS status;
223
224                 /* Check NT error */
225
226                 status = smbcli_nt_error(c->tree);
227
228                 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
229                         printf("unexpected error code %s\n", nt_errstr(status));
230                         printf(" expected %s (at %s)\n", nt_errstr(nterr), location);
231                         return False;
232                 }
233         }
234
235         return True;
236 }
237
238
239 static BOOL wait_lock(struct smbcli_state *c, int fnum, uint32_t offset, uint32_t len)
240 {
241         while (NT_STATUS_IS_ERR(smbcli_lock(c->tree, fnum, offset, len, -1, WRITE_LOCK))) {
242                 if (!check_error(__location__, c, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
243         }
244         return True;
245 }
246
247
248 static BOOL rw_torture(struct smbcli_state *c)
249 {
250         const char *lockfname = "\\torture.lck";
251         char *fname;
252         int fnum;
253         int fnum2;
254         pid_t pid2, pid = getpid();
255         int i, j;
256         char buf[1024];
257         BOOL correct = True;
258
259         fnum2 = smbcli_open(c->tree, lockfname, O_RDWR | O_CREAT | O_EXCL, 
260                          DENY_NONE);
261         if (fnum2 == -1)
262                 fnum2 = smbcli_open(c->tree, lockfname, O_RDWR, DENY_NONE);
263         if (fnum2 == -1) {
264                 printf("open of %s failed (%s)\n", lockfname, smbcli_errstr(c->tree));
265                 return False;
266         }
267
268
269         for (i=0;i<torture_numops;i++) {
270                 uint_t n = (uint_t)sys_random()%10;
271                 if (i % 10 == 0) {
272                         printf("%d\r", i); fflush(stdout);
273                 }
274                 asprintf(&fname, "\\torture.%u", n);
275
276                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
277                         return False;
278                 }
279
280                 fnum = smbcli_open(c->tree, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
281                 if (fnum == -1) {
282                         printf("open failed (%s)\n", smbcli_errstr(c->tree));
283                         correct = False;
284                         break;
285                 }
286
287                 if (smbcli_write(c->tree, fnum, 0, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
288                         printf("write failed (%s)\n", smbcli_errstr(c->tree));
289                         correct = False;
290                 }
291
292                 for (j=0;j<50;j++) {
293                         if (smbcli_write(c->tree, fnum, 0, (char *)buf, 
294                                       sizeof(pid)+(j*sizeof(buf)), 
295                                       sizeof(buf)) != sizeof(buf)) {
296                                 printf("write failed (%s)\n", smbcli_errstr(c->tree));
297                                 correct = False;
298                         }
299                 }
300
301                 pid2 = 0;
302
303                 if (smbcli_read(c->tree, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
304                         printf("read failed (%s)\n", smbcli_errstr(c->tree));
305                         correct = False;
306                 }
307
308                 if (pid2 != pid) {
309                         printf("data corruption!\n");
310                         correct = False;
311                 }
312
313                 if (NT_STATUS_IS_ERR(smbcli_close(c->tree, fnum))) {
314                         printf("close failed (%s)\n", smbcli_errstr(c->tree));
315                         correct = False;
316                 }
317
318                 if (NT_STATUS_IS_ERR(smbcli_unlink(c->tree, fname))) {
319                         printf("unlink failed (%s)\n", smbcli_errstr(c->tree));
320                         correct = False;
321                 }
322
323                 if (NT_STATUS_IS_ERR(smbcli_unlock(c->tree, fnum2, n*sizeof(int), sizeof(int)))) {
324                         printf("unlock failed (%s)\n", smbcli_errstr(c->tree));
325                         correct = False;
326                 }
327                 free(fname);
328         }
329
330         smbcli_close(c->tree, fnum2);
331         smbcli_unlink(c->tree, lockfname);
332
333         printf("%d\n", i);
334
335         return correct;
336 }
337
338 static BOOL run_torture(struct smbcli_state *cli, int dummy)
339 {
340         BOOL ret;
341
342         ret = rw_torture(cli);
343         
344         if (!torture_close_connection(cli)) {
345                 ret = False;
346         }
347
348         return ret;
349 }
350
351 static BOOL rw_torture3(struct smbcli_state *c, const char *lockfname)
352 {
353         int fnum = -1;
354         uint_t i = 0;
355         char buf[131072];
356         char buf_rd[131072];
357         uint_t count;
358         uint_t countprev = 0;
359         ssize_t sent = 0;
360         BOOL correct = True;
361
362         srandom(1);
363         for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
364         {
365                 SIVAL(buf, i, sys_random());
366         }
367
368         if (procnum == 0)
369         {
370                 fnum = smbcli_open(c->tree, lockfname, O_RDWR | O_CREAT | O_EXCL, 
371                                 DENY_NONE);
372                 if (fnum == -1) {
373                         printf("first open read/write of %s failed (%s)\n",
374                                         lockfname, smbcli_errstr(c->tree));
375                         return False;
376                 }
377         }
378         else
379         {
380                 for (i = 0; i < 500 && fnum == -1; i++)
381                 {
382                         fnum = smbcli_open(c->tree, lockfname, O_RDONLY, 
383                                         DENY_NONE);
384                         msleep(10);
385                 }
386                 if (fnum == -1) {
387                         printf("second open read-only of %s failed (%s)\n",
388                                         lockfname, smbcli_errstr(c->tree));
389                         return False;
390                 }
391         }
392
393         i = 0;
394         for (count = 0; count < sizeof(buf); count += sent)
395         {
396                 if (count >= countprev) {
397                         printf("%d %8d\r", i, count);
398                         fflush(stdout);
399                         i++;
400                         countprev += (sizeof(buf) / 20);
401                 }
402
403                 if (procnum == 0)
404                 {
405                         sent = ((uint_t)sys_random()%(20))+ 1;
406                         if (sent > sizeof(buf) - count)
407                         {
408                                 sent = sizeof(buf) - count;
409                         }
410
411                         if (smbcli_write(c->tree, fnum, 0, buf+count, count, (size_t)sent) != sent) {
412                                 printf("write failed (%s)\n", smbcli_errstr(c->tree));
413                                 correct = False;
414                         }
415                 }
416                 else
417                 {
418                         sent = smbcli_read(c->tree, fnum, buf_rd+count, count,
419                                         sizeof(buf)-count);
420                         if (sent < 0)
421                         {
422                                 printf("read failed offset:%d size:%d (%s)\n",
423                                                 count, sizeof(buf)-count,
424                                                 smbcli_errstr(c->tree));
425                                 correct = False;
426                                 sent = 0;
427                         }
428                         if (sent > 0)
429                         {
430                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
431                                 {
432                                         printf("read/write compare failed\n");
433                                         printf("offset: %d req %d recvd %d\n",
434                                                 count, sizeof(buf)-count, sent);
435                                         correct = False;
436                                         break;
437                                 }
438                         }
439                 }
440
441         }
442
443         if (NT_STATUS_IS_ERR(smbcli_close(c->tree, fnum))) {
444                 printf("close failed (%s)\n", smbcli_errstr(c->tree));
445                 correct = False;
446         }
447
448         return correct;
449 }
450
451 static BOOL rw_torture2(struct smbcli_state *c1, struct smbcli_state *c2)
452 {
453         const char *lockfname = "\\torture2.lck";
454         int fnum1;
455         int fnum2;
456         int i;
457         uint8_t buf[131072];
458         uint8_t buf_rd[131072];
459         BOOL correct = True;
460         ssize_t bytes_read, bytes_written;
461
462         if (smbcli_deltree(c1->tree, lockfname) == -1) {
463                 printf("unlink failed (%s)\n", smbcli_errstr(c1->tree));
464         }
465
466         fnum1 = smbcli_open(c1->tree, lockfname, O_RDWR | O_CREAT | O_EXCL, 
467                          DENY_NONE);
468         if (fnum1 == -1) {
469                 printf("first open read/write of %s failed (%s)\n",
470                                 lockfname, smbcli_errstr(c1->tree));
471                 return False;
472         }
473         fnum2 = smbcli_open(c2->tree, lockfname, O_RDONLY, 
474                          DENY_NONE);
475         if (fnum2 == -1) {
476                 printf("second open read-only of %s failed (%s)\n",
477                                 lockfname, smbcli_errstr(c2->tree));
478                 smbcli_close(c1->tree, fnum1);
479                 return False;
480         }
481
482         printf("Checking data integrity over %d ops\n", torture_numops);
483
484         for (i=0;i<torture_numops;i++)
485         {
486                 size_t buf_size = ((uint_t)sys_random()%(sizeof(buf)-1))+ 1;
487                 if (i % 10 == 0) {
488                         printf("%d\r", i); fflush(stdout);
489                 }
490
491                 generate_random_buffer(buf, buf_size);
492
493                 if ((bytes_written = smbcli_write(c1->tree, fnum1, 0, buf, 0, buf_size)) != buf_size) {
494                         printf("write failed (%s)\n", smbcli_errstr(c1->tree));
495                         printf("wrote %d, expected %d\n", bytes_written, buf_size); 
496                         correct = False;
497                         break;
498                 }
499
500                 if ((bytes_read = smbcli_read(c2->tree, fnum2, buf_rd, 0, buf_size)) != buf_size) {
501                         printf("read failed (%s)\n", smbcli_errstr(c2->tree));
502                         printf("read %d, expected %d\n", bytes_read, buf_size); 
503                         correct = False;
504                         break;
505                 }
506
507                 if (memcmp(buf_rd, buf, buf_size) != 0)
508                 {
509                         printf("read/write compare failed\n");
510                         correct = False;
511                         break;
512                 }
513         }
514
515         if (NT_STATUS_IS_ERR(smbcli_close(c2->tree, fnum2))) {
516                 printf("close failed (%s)\n", smbcli_errstr(c2->tree));
517                 correct = False;
518         }
519         if (NT_STATUS_IS_ERR(smbcli_close(c1->tree, fnum1))) {
520                 printf("close failed (%s)\n", smbcli_errstr(c1->tree));
521                 correct = False;
522         }
523
524         if (NT_STATUS_IS_ERR(smbcli_unlink(c1->tree, lockfname))) {
525                 printf("unlink failed (%s)\n", smbcli_errstr(c1->tree));
526                 correct = False;
527         }
528
529         return correct;
530 }
531
532 static BOOL run_readwritetest(int dummy)
533 {
534         struct smbcli_state *cli1, *cli2;
535         BOOL test1, test2 = True;
536
537         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
538                 return False;
539         }
540
541         printf("starting readwritetest\n");
542
543         test1 = rw_torture2(cli1, cli2);
544         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
545
546         if (test1) {
547                 test2 = rw_torture2(cli1, cli1);
548                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
549         }
550
551         if (!torture_close_connection(cli1)) {
552                 test1 = False;
553         }
554
555         if (!torture_close_connection(cli2)) {
556                 test2 = False;
557         }
558
559         return (test1 && test2);
560 }
561
562 static BOOL run_readwritemulti(struct smbcli_state *cli, int dummy)
563 {
564         BOOL test;
565
566         test = rw_torture3(cli, "\\multitest.txt");
567
568         if (!torture_close_connection(cli)) {
569                 test = False;
570         }
571         
572         return test;
573 }
574
575
576 /*
577   this checks to see if a secondary tconx can use open files from an
578   earlier tconx
579  */
580 static BOOL run_tcon_test(int dummy)
581 {
582         struct smbcli_state *cli;
583         const char *fname = "\\tcontest.tmp";
584         int fnum1;
585         uint16_t cnum1, cnum2, cnum3;
586         uint16_t vuid1, vuid2;
587         char buf[4];
588         BOOL ret = True;
589         struct smbcli_tree *tree1;
590         const char *host = lp_parm_string(-1, "torture", "host");
591         const char *share = lp_parm_string(-1, "torture", "share");
592         const char *password = lp_parm_string(-1, "torture", "password");
593
594         if (!torture_open_connection(&cli)) {
595                 return False;
596         }
597
598         printf("starting tcontest\n");
599
600         if (smbcli_deltree(cli->tree, fname) == -1) {
601                 printf("unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
602         }
603
604         fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
605         if (fnum1 == -1) {
606                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
607                 return False;
608         }
609
610         cnum1 = cli->tree->tid;
611         vuid1 = cli->session->vuid;
612
613         memset(&buf, 0, 4); /* init buf so valgrind won't complain */
614         if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) != 4) {
615                 printf("initial write failed (%s)\n", smbcli_errstr(cli->tree));
616                 return False;
617         }
618
619         tree1 = cli->tree;      /* save old tree connection */
620         if (NT_STATUS_IS_ERR(smbcli_send_tconX(cli, share, "?????", password))) {
621                 printf("%s refused 2nd tree connect (%s)\n", host,
622                            smbcli_errstr(cli->tree));
623                 smbcli_shutdown(cli);
624                 return False;
625         }
626
627         cnum2 = cli->tree->tid;
628         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
629         vuid2 = cli->session->vuid + 1;
630
631         /* try a write with the wrong tid */
632         cli->tree->tid = cnum2;
633
634         if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
635                 printf("* server allows write with wrong TID\n");
636                 ret = False;
637         } else {
638                 printf("server fails write with wrong TID : %s\n", smbcli_errstr(cli->tree));
639         }
640
641
642         /* try a write with an invalid tid */
643         cli->tree->tid = cnum3;
644
645         if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
646                 printf("* server allows write with invalid TID\n");
647                 ret = False;
648         } else {
649                 printf("server fails write with invalid TID : %s\n", smbcli_errstr(cli->tree));
650         }
651
652         /* try a write with an invalid vuid */
653         cli->session->vuid = vuid2;
654         cli->tree->tid = cnum1;
655
656         if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
657                 printf("* server allows write with invalid VUID\n");
658                 ret = False;
659         } else {
660                 printf("server fails write with invalid VUID : %s\n", smbcli_errstr(cli->tree));
661         }
662
663         cli->session->vuid = vuid1;
664         cli->tree->tid = cnum1;
665
666         if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum1))) {
667                 printf("close failed (%s)\n", smbcli_errstr(cli->tree));
668                 return False;
669         }
670
671         cli->tree->tid = cnum2;
672
673         if (NT_STATUS_IS_ERR(smbcli_tdis(cli))) {
674                 printf("secondary tdis failed (%s)\n", smbcli_errstr(cli->tree));
675                 return False;
676         }
677
678         cli->tree = tree1;  /* restore initial tree */
679         cli->tree->tid = cnum1;
680
681         if (!torture_close_connection(cli)) {
682                 return False;
683         }
684
685         return ret;
686 }
687
688
689
690 static BOOL tcon_devtest(struct smbcli_state *cli,
691                          const char *myshare, const char *devtype,
692                          NTSTATUS expected_error)
693 {
694         BOOL status;
695         BOOL ret;
696         const char *password = lp_parm_string(-1, "torture", "password");
697
698         status = NT_STATUS_IS_OK(smbcli_send_tconX(cli, myshare, devtype, 
699                                                 password));
700
701         printf("Trying share %s with devtype %s\n", myshare, devtype);
702
703         if (NT_STATUS_IS_OK(expected_error)) {
704                 if (status) {
705                         ret = True;
706                 } else {
707                         printf("tconX to share %s with type %s "
708                                "should have succeeded but failed\n",
709                                myshare, devtype);
710                         ret = False;
711                 }
712                 smbcli_tdis(cli);
713         } else {
714                 if (status) {
715                         printf("tconx to share %s with type %s "
716                                "should have failed but succeeded\n",
717                                myshare, devtype);
718                         ret = False;
719                 } else {
720                         if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),
721                                             expected_error)) {
722                                 ret = True;
723                         } else {
724                                 printf("Returned unexpected error\n");
725                                 ret = False;
726                         }
727                 }
728         }
729         return ret;
730 }
731
732 /*
733  checks for correct tconX support
734  */
735 static BOOL run_tcon_devtype_test(int dummy)
736 {
737         struct smbcli_state *cli1 = NULL;
738         BOOL retry;
739         int flags = 0;
740         NTSTATUS status;
741         BOOL ret = True;
742         const char *host = lp_parm_string(-1, "torture", "host");
743         const char *share = lp_parm_string(-1, "torture", "share");
744         const char *username = lp_parm_string(-1, "torture", "username");
745         const char *userdomain = lp_parm_string(-1, "torture", "userdomain");
746         const char *password = lp_parm_string(-1, "torture", "password");
747         
748         status = smbcli_full_connection(NULL,
749                                         &cli1, lp_netbios_name(),
750                                         host, NULL, 
751                                         share, "?????",
752                                         username, userdomain,
753                                         password, flags, &retry);
754
755         if (!NT_STATUS_IS_OK(status)) {
756                 printf("could not open connection\n");
757                 return False;
758         }
759
760         if (!tcon_devtest(cli1, "IPC$", "A:", NT_STATUS_BAD_DEVICE_TYPE))
761                 ret = False;
762
763         if (!tcon_devtest(cli1, "IPC$", "?????", NT_STATUS_OK))
764                 ret = False;
765
766         if (!tcon_devtest(cli1, "IPC$", "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
767                 ret = False;
768
769         if (!tcon_devtest(cli1, "IPC$", "IPC", NT_STATUS_OK))
770                 ret = False;
771                         
772         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
773                 ret = False;
774
775         if (!tcon_devtest(cli1, share, "A:", NT_STATUS_OK))
776                 ret = False;
777
778         if (!tcon_devtest(cli1, share, "?????", NT_STATUS_OK))
779                 ret = False;
780
781         if (!tcon_devtest(cli1, share, "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
782                 ret = False;
783
784         if (!tcon_devtest(cli1, share, "IPC", NT_STATUS_BAD_DEVICE_TYPE))
785                 ret = False;
786                         
787         if (!tcon_devtest(cli1, share, "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
788                 ret = False;
789
790         smbcli_shutdown(cli1);
791
792         if (ret)
793                 printf("Passed tcondevtest\n");
794
795         return ret;
796 }
797
798
799 /*
800 test whether fnums and tids open on one VC are available on another (a major
801 security hole)
802 */
803 static BOOL run_fdpasstest(int dummy)
804 {
805         struct smbcli_state *cli1, *cli2;
806         const char *fname = "\\fdpass.tst";
807         int fnum1, oldtid;
808         pstring buf;
809
810         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
811                 return False;
812         }
813
814         printf("starting fdpasstest\n");
815
816         smbcli_unlink(cli1->tree, fname);
817
818         printf("Opening a file on connection 1\n");
819
820         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
821         if (fnum1 == -1) {
822                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
823                 return False;
824         }
825
826         printf("writing to file on connection 1\n");
827
828         if (smbcli_write(cli1->tree, fnum1, 0, "hello world\n", 0, 13) != 13) {
829                 printf("write failed (%s)\n", smbcli_errstr(cli1->tree));
830                 return False;
831         }
832
833         oldtid = cli2->tree->tid;
834         cli2->session->vuid = cli1->session->vuid;
835         cli2->tree->tid = cli1->tree->tid;
836         cli2->session->pid = cli1->session->pid;
837
838         printf("reading from file on connection 2\n");
839
840         if (smbcli_read(cli2->tree, fnum1, buf, 0, 13) == 13) {
841                 printf("read succeeded! nasty security hole [%s]\n",
842                        buf);
843                 return False;
844         }
845
846         smbcli_close(cli1->tree, fnum1);
847         smbcli_unlink(cli1->tree, fname);
848
849         cli2->tree->tid = oldtid;
850
851         torture_close_connection(cli1);
852         torture_close_connection(cli2);
853
854         printf("finished fdpasstest\n");
855         return True;
856 }
857
858
859 /*
860   This test checks that 
861
862   1) the server does not allow an unlink on a file that is open
863 */
864 static BOOL run_unlinktest(int dummy)
865 {
866         struct smbcli_state *cli;
867         const char *fname = "\\unlink.tst";
868         int fnum;
869         BOOL correct = True;
870
871         if (!torture_open_connection(&cli)) {
872                 return False;
873         }
874
875         printf("starting unlink test\n");
876
877         smbcli_unlink(cli->tree, fname);
878
879         cli->session->pid = 1;
880
881         printf("Opening a file\n");
882
883         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
884         if (fnum == -1) {
885                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
886                 return False;
887         }
888
889         printf("Unlinking a open file\n");
890
891         if (NT_STATUS_IS_OK(smbcli_unlink(cli->tree, fname))) {
892                 printf("error: server allowed unlink on an open file\n");
893                 correct = False;
894         } else {
895                 correct = check_error(__location__, cli, ERRDOS, ERRbadshare, 
896                                       NT_STATUS_SHARING_VIOLATION);
897         }
898
899         smbcli_close(cli->tree, fnum);
900         smbcli_unlink(cli->tree, fname);
901
902         if (!torture_close_connection(cli)) {
903                 correct = False;
904         }
905
906         printf("unlink test finished\n");
907         
908         return correct;
909 }
910
911
912 /*
913 test the timing of deferred open requests
914 */
915 static BOOL run_deferopen(struct smbcli_state *cli, int dummy)
916 {
917         const char *fname = "\\defer_open_test.dat";
918         int retries=4;
919         int i = 0;
920         BOOL correct = True;
921
922         if (retries <= 0) {
923                 printf("failed to connect\n");
924                 return False;
925         }
926
927         printf("Testing deferred open requests.\n");
928
929         while (i < 4) {
930                 int fnum = -1;
931
932                 do {
933                         struct timeval tv_start, tv_end;
934                         GetTimeOfDay(&tv_start);
935                         fnum = smbcli_nt_create_full(cli->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS,
936                                 FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE,
937                                 NTCREATEX_DISP_OPEN_IF, 0, 0);
938                         if (fnum != -1) {
939                                 break;
940                         }
941                         GetTimeOfDay(&tv_end);
942                         if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION)) {
943                                 /* Sharing violation errors need to be 1 second apart. */
944                                 int64_t tdif = usec_time_diff(&tv_end, &tv_start);
945                                 if (tdif < 500000 || tdif > 1500000) {
946                                         fprintf(stderr,"Timing incorrect %lld.%lld for share violation\n",
947                                                 tdif / (int64_t)1000000, 
948                                                 tdif % (int64_t)1000000);
949                                 }
950                         }
951                 } while (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION));
952
953                 if (fnum == -1) {
954                         fprintf(stderr,"Failed to open %s, error=%s\n", fname, smbcli_errstr(cli->tree));
955                         return False;
956                 }
957
958                 printf("pid %u open %d\n", getpid(), i);
959
960                 sleep(10);
961                 i++;
962                 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum))) {
963                         fprintf(stderr,"Failed to close %s, error=%s\n", fname, smbcli_errstr(cli->tree));
964                         return False;
965                 }
966                 sleep(2);
967         }
968
969         if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
970                 /* All until the last unlink will fail with sharing violation. */
971                 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION)) {
972                         printf("unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
973                         correct = False;
974                 }
975         }
976
977         printf("deferred test finished\n");
978         if (!torture_close_connection(cli)) {
979                 correct = False;
980         }
981         return correct;
982 }
983
984 /*
985 test how many open files this server supports on the one socket
986 */
987 static BOOL run_maxfidtest(struct smbcli_state *cli, int dummy)
988 {
989 #define MAXFID_TEMPLATE "\\maxfid.%d.%d"
990         char *fname;
991         int fnums[0x11000], i;
992         int retries=4;
993         BOOL correct = True;
994
995         if (retries <= 0) {
996                 printf("failed to connect\n");
997                 return False;
998         }
999
1000         printf("Testing maximum number of open files\n");
1001
1002         for (i=0; i<0x11000; i++) {
1003                 asprintf(&fname, MAXFID_TEMPLATE, i,(int)getpid());
1004                 if ((fnums[i] = smbcli_open(cli->tree, fname, 
1005                                         O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) ==
1006                     -1) {
1007                         printf("open of %s failed (%s)\n", 
1008                                fname, smbcli_errstr(cli->tree));
1009                         printf("maximum fnum is %d\n", i);
1010                         break;
1011                 }
1012                 free(fname);
1013                 printf("%6d\r", i);
1014         }
1015         printf("%6d\n", i);
1016         i--;
1017
1018         printf("cleaning up\n");
1019         for (;i>=0;i--) {
1020                 asprintf(&fname, MAXFID_TEMPLATE, i,(int)getpid());
1021                 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[i]))) {
1022                         printf("Close of fnum %d failed - %s\n", fnums[i], smbcli_errstr(cli->tree));
1023                 }
1024                 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
1025                         printf("unlink of %s failed (%s)\n", 
1026                                fname, smbcli_errstr(cli->tree));
1027                         correct = False;
1028                 }
1029                 free(fname);
1030                 printf("%6d\r", i);
1031         }
1032         printf("%6d\n", 0);
1033
1034         printf("maxfid test finished\n");
1035         if (!torture_close_connection(cli)) {
1036                 correct = False;
1037         }
1038         return correct;
1039 #undef MAXFID_TEMPLATE
1040 }
1041
1042 /* send smb negprot commands, not reading the response */
1043 static BOOL run_negprot_nowait(int dummy)
1044 {
1045         int i;
1046         struct smbcli_state *cli, *cli2;
1047         BOOL correct = True;
1048
1049         printf("starting negprot nowait test\n");
1050
1051         cli = open_nbt_connection();
1052         if (!cli) {
1053                 return False;
1054         }
1055
1056         printf("Filling send buffer\n");
1057
1058         for (i=0;i<10000;i++) {
1059                 struct smbcli_request *req;
1060                 time_t t1 = time(NULL);
1061                 req = smb_negprot_send(cli->transport, PROTOCOL_NT1);
1062                 while (req->state == SMBCLI_REQUEST_SEND && time(NULL) < t1+5) {
1063                         smbcli_transport_process(cli->transport);
1064                 }
1065                 if (req->state == SMBCLI_REQUEST_ERROR) {
1066                         printf("Failed to fill pipe - %s\n", nt_errstr(req->status));
1067                         torture_close_connection(cli);
1068                         return correct;
1069                 }
1070                 if (req->state == SMBCLI_REQUEST_SEND) {
1071                         break;
1072                 }
1073         }
1074
1075         if (i == 10000) {
1076                 printf("send buffer failed to fill\n");
1077                 if (!torture_close_connection(cli)) {
1078                         correct = False;
1079                 }
1080                 return correct;
1081         }
1082
1083         printf("send buffer filled after %d requests\n", i);
1084
1085         printf("Opening secondary connection\n");
1086         if (!torture_open_connection(&cli2)) {
1087                 return False;
1088         }
1089
1090         if (!torture_close_connection(cli)) {
1091                 correct = False;
1092         }
1093
1094         if (!torture_close_connection(cli2)) {
1095                 correct = False;
1096         }
1097
1098         printf("finished negprot nowait test\n");
1099
1100         return correct;
1101 }
1102
1103
1104 /*
1105   This checks how the getatr calls works
1106 */
1107 static BOOL run_attrtest(int dummy)
1108 {
1109         struct smbcli_state *cli;
1110         int fnum;
1111         time_t t, t2;
1112         const char *fname = "\\attrib123456789.tst";
1113         BOOL correct = True;
1114
1115         printf("starting attrib test\n");
1116
1117         if (!torture_open_connection(&cli)) {
1118                 return False;
1119         }
1120
1121         smbcli_unlink(cli->tree, fname);
1122         fnum = smbcli_open(cli->tree, fname, 
1123                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1124         smbcli_close(cli->tree, fnum);
1125
1126         if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
1127                 printf("getatr failed (%s)\n", smbcli_errstr(cli->tree));
1128                 correct = False;
1129         }
1130
1131         printf("New file time is %s", ctime(&t));
1132
1133         if (abs(t - time(NULL)) > 60*60*24*10) {
1134                 printf("ERROR: SMBgetatr bug. time is %s",
1135                        ctime(&t));
1136                 t = time(NULL);
1137                 correct = False;
1138         }
1139
1140         t2 = t-60*60*24; /* 1 day ago */
1141
1142         printf("Setting file time to %s", ctime(&t2));
1143
1144         if (NT_STATUS_IS_ERR(smbcli_setatr(cli->tree, fname, 0, t2))) {
1145                 printf("setatr failed (%s)\n", smbcli_errstr(cli->tree));
1146                 correct = True;
1147         }
1148
1149         if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
1150                 printf("getatr failed (%s)\n", smbcli_errstr(cli->tree));
1151                 correct = True;
1152         }
1153
1154         printf("Retrieved file time as %s", ctime(&t));
1155
1156         if (t != t2) {
1157                 printf("ERROR: getatr/setatr bug. times are\n%s",
1158                        ctime(&t));
1159                 printf("%s", ctime(&t2));
1160                 correct = True;
1161         }
1162
1163         smbcli_unlink(cli->tree, fname);
1164
1165         if (!torture_close_connection(cli)) {
1166                 correct = False;
1167         }
1168
1169         printf("attrib test finished\n");
1170
1171         return correct;
1172 }
1173
1174
1175 /*
1176   This checks a couple of trans2 calls
1177 */
1178 static BOOL run_trans2test(int dummy)
1179 {
1180         struct smbcli_state *cli;
1181         int fnum;
1182         size_t size;
1183         time_t c_time, a_time, m_time, w_time, m_time2;
1184         const char *fname = "\\trans2.tst";
1185         const char *dname = "\\trans2";
1186         const char *fname2 = "\\trans2\\trans2.tst";
1187         const char *pname;
1188         BOOL correct = True;
1189
1190         printf("starting trans2 test\n");
1191
1192         if (!torture_open_connection(&cli)) {
1193                 return False;
1194         }
1195
1196         smbcli_unlink(cli->tree, fname);
1197
1198         printf("Testing qfileinfo\n");
1199         
1200         fnum = smbcli_open(cli->tree, fname, 
1201                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1202         if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, NULL, &size, &c_time, &a_time, &m_time,
1203                            NULL, NULL))) {
1204                 printf("ERROR: qfileinfo failed (%s)\n", smbcli_errstr(cli->tree));
1205                 correct = False;
1206         }
1207
1208         printf("Testing NAME_INFO\n");
1209
1210         if (NT_STATUS_IS_ERR(smbcli_qfilename(cli->tree, fnum, &pname))) {
1211                 printf("ERROR: qfilename failed (%s)\n", smbcli_errstr(cli->tree));
1212                 correct = False;
1213         }
1214
1215         if (!pname || strcmp(pname, fname)) {
1216                 printf("qfilename gave different name? [%s] [%s]\n",
1217                        fname, pname);
1218                 correct = False;
1219         }
1220
1221         smbcli_close(cli->tree, fnum);
1222         smbcli_unlink(cli->tree, fname);
1223
1224         fnum = smbcli_open(cli->tree, fname, 
1225                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1226         if (fnum == -1) {
1227                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
1228                 return False;
1229         }
1230         smbcli_close(cli->tree, fnum);
1231
1232         printf("Checking for sticky create times\n");
1233
1234         if (NT_STATUS_IS_ERR(smbcli_qpathinfo(cli->tree, fname, &c_time, &a_time, &m_time, &size, NULL))) {
1235                 printf("ERROR: qpathinfo failed (%s)\n", smbcli_errstr(cli->tree));
1236                 correct = False;
1237         } else {
1238                 if (c_time != m_time) {
1239                         printf("create time=%s", ctime(&c_time));
1240                         printf("modify time=%s", ctime(&m_time));
1241                         printf("This system appears to have sticky create times\n");
1242                 }
1243                 if (a_time % (60*60) == 0) {
1244                         printf("access time=%s", ctime(&a_time));
1245                         printf("This system appears to set a midnight access time\n");
1246                         correct = False;
1247                 }
1248
1249                 if (abs(m_time - time(NULL)) > 60*60*24*7) {
1250                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
1251                         correct = False;
1252                 }
1253         }
1254
1255
1256         smbcli_unlink(cli->tree, fname);
1257         fnum = smbcli_open(cli->tree, fname, 
1258                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1259         smbcli_close(cli->tree, fnum);
1260         if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, fname, &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
1261                 printf("ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
1262                 correct = False;
1263         } else {
1264                 if (w_time < 60*60*24*2) {
1265                         printf("write time=%s", ctime(&w_time));
1266                         printf("This system appears to set a initial 0 write time\n");
1267                         correct = False;
1268                 }
1269         }
1270
1271         smbcli_unlink(cli->tree, fname);
1272
1273
1274         /* check if the server updates the directory modification time
1275            when creating a new file */
1276         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) {
1277                 printf("ERROR: mkdir failed (%s)\n", smbcli_errstr(cli->tree));
1278                 correct = False;
1279         }
1280         sleep(3);
1281         if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
1282                 printf("ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
1283                 correct = False;
1284         }
1285
1286         fnum = smbcli_open(cli->tree, fname2, 
1287                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1288         smbcli_write(cli->tree, fnum,  0, (char *)&fnum, 0, sizeof(fnum));
1289         smbcli_close(cli->tree, fnum);
1290         if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time2, &w_time, &size, NULL, NULL))) {
1291                 printf("ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
1292                 correct = False;
1293         } else {
1294                 if (m_time2 == m_time) {
1295                         printf("This system does not update directory modification times\n");
1296                         correct = False;
1297                 }
1298         }
1299         smbcli_unlink(cli->tree, fname2);
1300         smbcli_rmdir(cli->tree, dname);
1301
1302         if (!torture_close_connection(cli)) {
1303                 correct = False;
1304         }
1305
1306         printf("trans2 test finished\n");
1307
1308         return correct;
1309 }
1310
1311 /*
1312   Test delete on close semantics.
1313  */
1314 static BOOL run_deletetest(int dummy)
1315 {
1316         struct smbcli_state *cli1;
1317         struct smbcli_state *cli2 = NULL;
1318         const char *fname = "\\delete.file";
1319         int fnum1 = -1;
1320         int fnum2 = -1;
1321         BOOL correct = True;
1322         NTSTATUS status;
1323         
1324         printf("starting delete test\n");
1325         
1326         if (!torture_open_connection(&cli1)) {
1327                 return False;
1328         }
1329         
1330         /* Test 1 - this should delete the file on close. */
1331         
1332         smbcli_setatr(cli1->tree, fname, 0, 0);
1333         smbcli_unlink(cli1->tree, fname);
1334         
1335         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
1336                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 
1337                                    NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1338         
1339         if (fnum1 == -1) {
1340                 printf("[1] open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1341                 correct = False;
1342                 goto fail;
1343         }
1344         
1345         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1346                 printf("[1] close failed (%s)\n", smbcli_errstr(cli1->tree));
1347                 correct = False;
1348                 goto fail;
1349         }
1350
1351         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1352         if (fnum1 != -1) {
1353                 printf("[1] open of %s succeeded (should fail)\n", fname);
1354                 correct = False;
1355                 goto fail;
1356         }
1357         
1358         printf("first delete on close test succeeded.\n");
1359         
1360         /* Test 2 - this should delete the file on close. */
1361         
1362         smbcli_setatr(cli1->tree, fname, 0, 0);
1363         smbcli_unlink(cli1->tree, fname);
1364         
1365         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS,
1366                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, 
1367                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1368         
1369         if (fnum1 == -1) {
1370                 printf("[2] open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1371                 correct = False;
1372                 goto fail;
1373         }
1374         
1375         if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
1376                 printf("[2] setting delete_on_close failed (%s)\n", smbcli_errstr(cli1->tree));
1377                 correct = False;
1378                 goto fail;
1379         }
1380         
1381         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1382                 printf("[2] close failed (%s)\n", smbcli_errstr(cli1->tree));
1383                 correct = False;
1384                 goto fail;
1385         }
1386         
1387         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
1388         if (fnum1 != -1) {
1389                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
1390                 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1391                         printf("[2] close failed (%s)\n", smbcli_errstr(cli1->tree));
1392                         correct = False;
1393                         goto fail;
1394                 }
1395                 smbcli_unlink(cli1->tree, fname);
1396         } else
1397                 printf("second delete on close test succeeded.\n");
1398         
1399         /* Test 3 - ... */
1400         smbcli_setatr(cli1->tree, fname, 0, 0);
1401         smbcli_unlink(cli1->tree, fname);
1402
1403         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
1404                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1405
1406         if (fnum1 == -1) {
1407                 printf("[3] open - 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1408                 correct = False;
1409                 goto fail;
1410         }
1411
1412         /* This should fail with a sharing violation - open for delete is only compatible
1413            with SHARE_DELETE. */
1414
1415         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
1416                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
1417                                    NTCREATEX_DISP_OPEN, 0, 0);
1418
1419         if (fnum2 != -1) {
1420                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
1421                 correct = False;
1422                 goto fail;
1423         }
1424
1425         /* This should succeed. */
1426
1427         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
1428                         NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN, 0, 0);
1429
1430         if (fnum2 == -1) {
1431                 printf("[3] open  - 2 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1432                 correct = False;
1433                 goto fail;
1434         }
1435
1436         if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
1437                 printf("[3] setting delete_on_close failed (%s)\n", smbcli_errstr(cli1->tree));
1438                 correct = False;
1439                 goto fail;
1440         }
1441         
1442         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1443                 printf("[3] close 1 failed (%s)\n", smbcli_errstr(cli1->tree));
1444                 correct = False;
1445                 goto fail;
1446         }
1447         
1448         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
1449                 printf("[3] close 2 failed (%s)\n", smbcli_errstr(cli1->tree));
1450                 correct = False;
1451                 goto fail;
1452         }
1453         
1454         /* This should fail - file should no longer be there. */
1455
1456         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
1457         if (fnum1 != -1) {
1458                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
1459                 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1460                         printf("[3] close failed (%s)\n", smbcli_errstr(cli1->tree));
1461                 }
1462                 smbcli_unlink(cli1->tree, fname);
1463                 correct = False;
1464                 goto fail;
1465         } else
1466                 printf("third delete on close test succeeded.\n");
1467
1468         /* Test 4 ... */
1469         smbcli_setatr(cli1->tree, fname, 0, 0);
1470         smbcli_unlink(cli1->tree, fname);
1471
1472         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
1473                                    SA_RIGHT_FILE_READ_DATA  | 
1474                                    SA_RIGHT_FILE_WRITE_DATA |
1475                                    STD_RIGHT_DELETE_ACCESS,
1476                                    FILE_ATTRIBUTE_NORMAL, 
1477                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
1478                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1479                                                                 
1480         if (fnum1 == -1) {
1481                 printf("[4] open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1482                 correct = False;
1483                 goto fail;
1484         }
1485
1486         /* This should succeed. */
1487         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ,
1488                                    FILE_ATTRIBUTE_NORMAL, 
1489                                    NTCREATEX_SHARE_ACCESS_READ  | 
1490                                    NTCREATEX_SHARE_ACCESS_WRITE |
1491                                    NTCREATEX_SHARE_ACCESS_DELETE, 
1492                                    NTCREATEX_DISP_OPEN, 0, 0);
1493         if (fnum2 == -1) {
1494                 printf("[4] open  - 2 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1495                 correct = False;
1496                 goto fail;
1497         }
1498         
1499         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
1500                 printf("[4] close - 1 failed (%s)\n", smbcli_errstr(cli1->tree));
1501                 correct = False;
1502                 goto fail;
1503         }
1504         
1505         if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
1506                 printf("[4] setting delete_on_close failed (%s)\n", smbcli_errstr(cli1->tree));
1507                 correct = False;
1508                 goto fail;
1509         }
1510         
1511         /* This should fail - no more opens once delete on close set. */
1512         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ,
1513                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
1514                                    NTCREATEX_DISP_OPEN, 0, 0);
1515         if (fnum2 != -1) {
1516                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
1517                 correct = False;
1518                 goto fail;
1519         } else
1520                 printf("fourth delete on close test succeeded.\n");
1521         
1522         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1523                 printf("[4] close - 2 failed (%s)\n", smbcli_errstr(cli1->tree));
1524                 correct = False;
1525                 goto fail;
1526         }
1527         
1528         /* Test 5 ... */
1529         smbcli_setatr(cli1->tree, fname, 0, 0);
1530         smbcli_unlink(cli1->tree, fname);
1531         
1532         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1533         if (fnum1 == -1) {
1534                 printf("[5] open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1535                 correct = False;
1536                 goto fail;
1537         }
1538
1539         /* This should fail - only allowed on NT opens with DELETE access. */
1540
1541         if (NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
1542                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
1543                 correct = False;
1544                 goto fail;
1545         }
1546
1547         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1548                 printf("[5] close - 2 failed (%s)\n", smbcli_errstr(cli1->tree));
1549                 correct = False;
1550                 goto fail;
1551         }
1552         
1553         printf("fifth delete on close test succeeded.\n");
1554         
1555         /* Test 6 ... */
1556         smbcli_setatr(cli1->tree, fname, 0, 0);
1557         smbcli_unlink(cli1->tree, fname);
1558         
1559         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
1560                                    SA_RIGHT_FILE_READ_DATA | SA_RIGHT_FILE_WRITE_DATA,
1561                                    FILE_ATTRIBUTE_NORMAL, 
1562                                    NTCREATEX_SHARE_ACCESS_READ  |
1563                                    NTCREATEX_SHARE_ACCESS_WRITE |
1564                                    NTCREATEX_SHARE_ACCESS_DELETE,
1565                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1566         
1567         if (fnum1 == -1) {
1568                 printf("[6] open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1569                 correct = False;
1570                 goto fail;
1571         }
1572         
1573         /* This should fail - only allowed on NT opens with DELETE access. */
1574         
1575         if (NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
1576                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
1577                 correct = False;
1578                 goto fail;
1579         }
1580
1581         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1582                 printf("[6] close - 2 failed (%s)\n", smbcli_errstr(cli1->tree));
1583                 correct = False;
1584                 goto fail;
1585         }
1586
1587         printf("sixth delete on close test succeeded.\n");
1588         
1589         /* Test 7 ... */
1590         smbcli_setatr(cli1->tree, fname, 0, 0);
1591         smbcli_unlink(cli1->tree, fname);
1592         
1593         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
1594                                    SA_RIGHT_FILE_READ_DATA  | 
1595                                    SA_RIGHT_FILE_WRITE_DATA |
1596                                    STD_RIGHT_DELETE_ACCESS,
1597                                    FILE_ATTRIBUTE_NORMAL, 0, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1598                                                                 
1599         if (fnum1 == -1) {
1600                 printf("[7] open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1601                 correct = False;
1602                 goto fail;
1603         }
1604
1605         if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
1606                 printf("[7] setting delete_on_close on file failed !\n");
1607                 correct = False;
1608                 goto fail;
1609         }
1610         
1611         if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, False))) {
1612                 printf("[7] unsetting delete_on_close on file failed !\n");
1613                 correct = False;
1614                 goto fail;
1615         }
1616
1617         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1618                 printf("[7] close - 2 failed (%s)\n", smbcli_errstr(cli1->tree));
1619                 correct = False;
1620                 goto fail;
1621         }
1622         
1623         /* This next open should succeed - we reset the flag. */
1624         
1625         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
1626         if (fnum1 == -1) {
1627                 printf("[5] open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1628                 correct = False;
1629                 goto fail;
1630         }
1631
1632         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1633                 printf("[7] close - 2 failed (%s)\n", smbcli_errstr(cli1->tree));
1634                 correct = False;
1635                 goto fail;
1636         }
1637
1638         printf("seventh delete on close test succeeded.\n");
1639         
1640         /* Test 7 ... */
1641         smbcli_setatr(cli1->tree, fname, 0, 0);
1642         smbcli_unlink(cli1->tree, fname);
1643         
1644         if (!torture_open_connection(&cli2)) {
1645                 printf("[8] failed to open second connection.\n");
1646                 correct = False;
1647                 goto fail;
1648         }
1649
1650         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|STD_RIGHT_DELETE_ACCESS,
1651                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
1652                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1653         
1654         if (fnum1 == -1) {
1655                 printf("[8] open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1656                 correct = False;
1657                 goto fail;
1658         }
1659
1660         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|STD_RIGHT_DELETE_ACCESS,
1661                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
1662                                    NTCREATEX_DISP_OPEN, 0, 0);
1663         
1664         if (fnum2 == -1) {
1665                 printf("[8] open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1666                 correct = False;
1667                 goto fail;
1668         }
1669
1670         if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
1671                 printf("[8] setting delete_on_close on file failed !\n");
1672                 correct = False;
1673                 goto fail;
1674         }
1675         
1676         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1677                 printf("[8] close - 1 failed (%s)\n", smbcli_errstr(cli1->tree));
1678                 correct = False;
1679                 goto fail;
1680         }
1681
1682         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1683                 printf("[8] close - 2 failed (%s)\n", smbcli_errstr(cli2->tree));
1684                 correct = False;
1685                 goto fail;
1686         }
1687
1688         /* This should fail.. */
1689         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
1690         if (fnum1 != -1) {
1691                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
1692                 goto fail;
1693                 correct = False;
1694         } else
1695                 printf("eighth delete on close test succeeded.\n");
1696
1697         /* This should fail - we need to set DELETE_ACCESS. */
1698         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA,
1699                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1700         
1701         if (fnum1 != -1) {
1702                 printf("[9] open of %s succeeded should have failed!\n", fname);
1703                 correct = False;
1704                 goto fail;
1705         }
1706
1707         printf("ninth delete on close test succeeded.\n");
1708
1709         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|STD_RIGHT_DELETE_ACCESS,
1710                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1711         if (fnum1 == -1) {
1712                 printf("[10] open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1713                 correct = False;
1714                 goto fail;
1715         }
1716
1717         /* This should delete the file. */
1718         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1719                 printf("[10] close failed (%s)\n", smbcli_errstr(cli1->tree));
1720                 correct = False;
1721                 goto fail;
1722         }
1723
1724         /* This should fail.. */
1725         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
1726         if (fnum1 != -1) {
1727                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
1728                 goto fail;
1729                 correct = False;
1730         } else
1731                 printf("tenth delete on close test succeeded.\n");
1732
1733         /* test 11 - does having read only attribute still allow delete on close. */
1734
1735         smbcli_setatr(cli1->tree, fname, 0, 0);
1736         smbcli_unlink(cli1->tree, fname);
1737                                                                                                                                         
1738         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS,
1739                                    FILE_ATTRIBUTE_READONLY, NTCREATEX_SHARE_ACCESS_NONE, 
1740                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1741         
1742         if (fnum1 == -1) {
1743                 printf("[11] open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1744                 correct = False;
1745                 goto fail;
1746         }
1747
1748         status = smbcli_nt_delete_on_close(cli1->tree, fnum1, True);
1749
1750         if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_CANNOT_DELETE)) {
1751                 printf("[11] setting delete_on_close should fail with NT_STATUS_CANNOT_DELETE. Got %s instead)\n", smbcli_errstr(cli1->tree));
1752                 correct = False;
1753                 goto fail;
1754         }
1755
1756         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1757                 printf("[11] close failed (%s)\n", smbcli_errstr(cli1->tree));
1758                 correct = False;
1759                 goto fail;
1760         }
1761
1762         smbcli_setatr(cli1->tree, fname, 0, 0);
1763         smbcli_unlink(cli1->tree, fname);
1764                                                                                                                                         
1765         printf("eleventh delete on close test succeeded.\n");
1766
1767         /* test 12 - does having read only attribute still allow delete on close at time of open. */
1768
1769         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS, FILE_ATTRIBUTE_READONLY,
1770                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 
1771                                    NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1772         
1773         if (fnum1 != -1) {
1774                 printf("[12] open of %s succeeded. Should fail with NT_STATUS_CANNOT_DELETE.\n", fname);
1775                 smbcli_close(cli1->tree, fnum1);
1776                 correct = False;
1777                 goto fail;
1778         } else {
1779                 status = smbcli_nt_error(cli1->tree);
1780                 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_CANNOT_DELETE)) {
1781                         printf("[12] setting delete_on_close on open should fail with NT_STATUS_CANNOT_DELETE. Got %s instead)\n", smbcli_errstr(cli1->tree));
1782                         correct = False;
1783                         goto fail;
1784                 }
1785         }
1786         
1787         printf("twelvth delete on close test succeeded.\n");
1788
1789         printf("finished delete test\n");
1790
1791   fail:
1792         /* FIXME: This will crash if we aborted before cli2 got
1793          * intialized, because these functions don't handle
1794          * uninitialized connections. */
1795                 
1796         smbcli_close(cli1->tree, fnum1);
1797         smbcli_close(cli1->tree, fnum2);
1798         smbcli_setatr(cli1->tree, fname, 0, 0);
1799         smbcli_unlink(cli1->tree, fname);
1800
1801         if (!torture_close_connection(cli1)) {
1802                 correct = False;
1803         }
1804         if (!torture_close_connection(cli2)) {
1805                 correct = False;
1806         }
1807         return correct;
1808 }
1809
1810
1811 /*
1812   print out server properties
1813  */
1814 static BOOL run_properties(int dummy)
1815 {
1816         struct smbcli_state *cli;
1817         BOOL correct = True;
1818         
1819         printf("starting properties test\n");
1820         
1821         ZERO_STRUCT(cli);
1822
1823         if (!torture_open_connection(&cli)) {
1824                 return False;
1825         }
1826         
1827         d_printf("Capabilities 0x%08x\n", cli->transport->negotiate.capabilities);
1828
1829         if (!torture_close_connection(cli)) {
1830                 correct = False;
1831         }
1832
1833         return correct;
1834 }
1835
1836
1837
1838 /* FIRST_DESIRED_ACCESS   0xf019f */
1839 #define FIRST_DESIRED_ACCESS   SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|SA_RIGHT_FILE_APPEND_DATA|\
1840                                SA_RIGHT_FILE_READ_EA|                           /* 0xf */ \
1841                                SA_RIGHT_FILE_WRITE_EA|SA_RIGHT_FILE_READ_ATTRIBUTES|     /* 0x90 */ \
1842                                SA_RIGHT_FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
1843                                STD_RIGHT_DELETE_ACCESS|STD_RIGHT_READ_CONTROL_ACCESS|\
1844                                STD_RIGHT_WRITE_DAC_ACCESS|STD_RIGHT_WRITE_OWNER_ACCESS     /* 0xf0000 */
1845 /* SECOND_DESIRED_ACCESS  0xe0080 */
1846 #define SECOND_DESIRED_ACCESS  SA_RIGHT_FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
1847                                STD_RIGHT_READ_CONTROL_ACCESS|STD_RIGHT_WRITE_DAC_ACCESS|\
1848                                STD_RIGHT_WRITE_OWNER_ACCESS                      /* 0xe0000 */
1849
1850 #if 0
1851 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
1852                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
1853                                SA_RIGHT_FILE_READ_DATA|\
1854                                WRITE_OWNER_ACCESS                      /* */
1855 #endif
1856
1857 /*
1858   Test ntcreate calls made by xcopy
1859  */
1860 static BOOL run_xcopy(int dummy)
1861 {
1862         struct smbcli_state *cli1;
1863         const char *fname = "\\test.txt";
1864         BOOL correct = True;
1865         int fnum1, fnum2;
1866
1867         printf("starting xcopy test\n");
1868         
1869         if (!torture_open_connection(&cli1)) {
1870                 return False;
1871         }
1872         
1873         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1874                                    FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
1875                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 
1876                                    0x4044, 0);
1877
1878         if (fnum1 == -1) {
1879                 printf("First open failed - %s\n", smbcli_errstr(cli1->tree));
1880                 return False;
1881         }
1882
1883         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1884                                    SECOND_DESIRED_ACCESS, 0,
1885                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN, 
1886                                    0x200000, 0);
1887         if (fnum2 == -1) {
1888                 printf("second open failed - %s\n", smbcli_errstr(cli1->tree));
1889                 return False;
1890         }
1891         
1892         if (!torture_close_connection(cli1)) {
1893                 correct = False;
1894         }
1895         
1896         return correct;
1897 }
1898
1899 /*
1900   Test rename on files open with share delete and no share delete.
1901  */
1902 static BOOL run_rename(int dummy)
1903 {
1904         struct smbcli_state *cli1;
1905         const char *fname = "\\test.txt";
1906         const char *fname1 = "\\test1.txt";
1907         BOOL correct = True;
1908         int fnum1;
1909
1910         printf("starting rename test\n");
1911         
1912         if (!torture_open_connection(&cli1)) {
1913                 return False;
1914         }
1915         
1916         smbcli_unlink(cli1->tree, fname);
1917         smbcli_unlink(cli1->tree, fname1);
1918         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
1919                                    NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1920
1921         if (fnum1 == -1) {
1922                 printf("First open failed - %s\n", smbcli_errstr(cli1->tree));
1923                 return False;
1924         }
1925
1926         if (NT_STATUS_IS_ERR(smbcli_rename(cli1->tree, fname, fname1))) {
1927                 printf("First rename failed (this is correct) - %s\n", smbcli_errstr(cli1->tree));
1928         } else {
1929                 printf("First rename succeeded - this should have failed !\n");
1930                 correct = False;
1931         }
1932
1933         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1934                 printf("close - 1 failed (%s)\n", smbcli_errstr(cli1->tree));
1935                 return False;
1936         }
1937
1938         smbcli_unlink(cli1->tree, fname);
1939         smbcli_unlink(cli1->tree, fname1);
1940         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
1941                                    NTCREATEX_SHARE_ACCESS_DELETE|NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1942
1943         if (fnum1 == -1) {
1944                 printf("Second open failed - %s\n", smbcli_errstr(cli1->tree));
1945                 return False;
1946         }
1947
1948         if (NT_STATUS_IS_ERR(smbcli_rename(cli1->tree, fname, fname1))) {
1949                 printf("Second rename failed - this should have succeeded - %s\n", smbcli_errstr(cli1->tree));
1950                 correct = False;
1951         } else {
1952                 printf("Second rename succeeded\n");
1953         }
1954
1955         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1956                 printf("close - 2 failed (%s)\n", smbcli_errstr(cli1->tree));
1957                 return False;
1958         }
1959
1960         smbcli_unlink(cli1->tree, fname);
1961         smbcli_unlink(cli1->tree, fname1);
1962
1963         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_READ_CONTROL_ACCESS, FILE_ATTRIBUTE_NORMAL,
1964                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1965
1966         if (fnum1 == -1) {
1967                 printf("Third open failed - %s\n", smbcli_errstr(cli1->tree));
1968                 return False;
1969         }
1970
1971
1972         if (NT_STATUS_IS_ERR(smbcli_rename(cli1->tree, fname, fname1))) {
1973                 printf("Third rename failed - this should have succeeded - %s\n", smbcli_errstr(cli1->tree));
1974                 correct = False;
1975         } else {
1976                 printf("Third rename succeeded\n");
1977         }
1978
1979         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1980                 printf("close - 3 failed (%s)\n", smbcli_errstr(cli1->tree));
1981                 return False;
1982         }
1983
1984         smbcli_unlink(cli1->tree, fname);
1985         smbcli_unlink(cli1->tree, fname1);
1986
1987         if (!torture_close_connection(cli1)) {
1988                 correct = False;
1989         }
1990         
1991         return correct;
1992 }
1993
1994
1995 /*
1996   see how many RPC pipes we can open at once
1997 */
1998 static BOOL run_pipe_number(int dummy)
1999 {
2000         struct smbcli_state *cli1;
2001         const char *pipe_name = "\\WKSSVC";
2002         int fnum;
2003         int num_pipes = 0;
2004
2005         printf("starting pipenumber test\n");
2006         if (!torture_open_connection(&cli1)) {
2007                 return False;
2008         }
2009
2010         while(1) {
2011                 fnum = smbcli_nt_create_full(cli1->tree, pipe_name, 0, SA_RIGHT_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
2012                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OPEN_IF, 0, 0);
2013
2014                 if (fnum == -1) {
2015                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, smbcli_errstr(cli1->tree));
2016                         break;
2017                 }
2018                 num_pipes++;
2019                 printf("%d\r", num_pipes);
2020                 fflush(stdout);
2021         }
2022
2023         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
2024         torture_close_connection(cli1);
2025         return True;
2026 }
2027
2028
2029
2030
2031 /*
2032   open N connections to the server and just hold them open
2033   used for testing performance when there are N idle users
2034   already connected
2035  */
2036  static BOOL torture_holdcon(int dummy)
2037 {
2038         int i;
2039         struct smbcli_state **cli;
2040         int num_dead = 0;
2041
2042         printf("Opening %d connections\n", torture_numops);
2043         
2044         cli = malloc(sizeof(struct smbcli_state *) * torture_numops);
2045
2046         for (i=0;i<torture_numops;i++) {
2047                 if (!torture_open_connection(&cli[i])) {
2048                         return False;
2049                 }
2050                 printf("opened %d connections\r", i);
2051                 fflush(stdout);
2052         }
2053
2054         printf("\nStarting pings\n");
2055
2056         while (1) {
2057                 for (i=0;i<torture_numops;i++) {
2058                         NTSTATUS status;
2059                         if (cli[i]) {
2060                                 status = smbcli_chkpath(cli[i]->tree, "\\");
2061                                 if (!NT_STATUS_IS_OK(status)) {
2062                                         printf("Connection %d is dead\n", i);
2063                                         cli[i] = NULL;
2064                                         num_dead++;
2065                                 }
2066                                 usleep(100);
2067                         }
2068                 }
2069
2070                 if (num_dead == torture_numops) {
2071                         printf("All connections dead - finishing\n");
2072                         break;
2073                 }
2074
2075                 printf(".");
2076                 fflush(stdout);
2077         }
2078
2079         return True;
2080 }
2081
2082 /*
2083   Try with a wrong vuid and check error message.
2084  */
2085
2086 static BOOL run_vuidtest(int dummy)
2087 {
2088         struct smbcli_state *cli;
2089         const char *fname = "\\vuid.tst";
2090         int fnum;
2091         size_t size;
2092         time_t c_time, a_time, m_time;
2093         BOOL correct = True;
2094
2095         uint16_t orig_vuid;
2096         NTSTATUS result;
2097
2098         printf("starting vuid test\n");
2099
2100         if (!torture_open_connection(&cli)) {
2101                 return False;
2102         }
2103
2104         smbcli_unlink(cli->tree, fname);
2105
2106         fnum = smbcli_open(cli->tree, fname, 
2107                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2108
2109         orig_vuid = cli->session->vuid;
2110
2111         cli->session->vuid += 1234;
2112
2113         printf("Testing qfileinfo with wrong vuid\n");
2114         
2115         if (NT_STATUS_IS_OK(result = smbcli_qfileinfo(cli->tree, fnum, NULL,
2116                                                    &size, &c_time, &a_time,
2117                                                    &m_time, NULL, NULL))) {
2118                 printf("ERROR: qfileinfo passed with wrong vuid\n");
2119                 correct = False;
2120         }
2121
2122         if ( (cli->transport->error.etype != ETYPE_DOS) ||
2123              (cli->transport->error.e.dos.eclass != ERRSRV) ||
2124              (cli->transport->error.e.dos.ecode != ERRbaduid) ) {
2125                 printf("ERROR: qfileinfo should have returned DOS error "
2126                        "ERRSRV:ERRbaduid\n  but returned %s\n",
2127                        smbcli_errstr(cli->tree));
2128                 correct = False;
2129         }
2130
2131         cli->session->vuid -= 1234;
2132
2133         if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum))) {
2134                 printf("close failed (%s)\n", smbcli_errstr(cli->tree));
2135                 correct = False;
2136         }
2137
2138         smbcli_unlink(cli->tree, fname);
2139
2140         if (!torture_close_connection(cli)) {
2141                 correct = False;
2142         }
2143
2144         printf("vuid test finished\n");
2145
2146         return correct;
2147 }
2148
2149 /*
2150   Test open mode returns on read-only files.
2151  */
2152  static BOOL run_opentest(int dummy)
2153 {
2154         static struct smbcli_state *cli1;
2155         static struct smbcli_state *cli2;
2156         const char *fname = "\\readonly.file";
2157         int fnum1, fnum2;
2158         char buf[20];
2159         size_t fsize;
2160         BOOL correct = True;
2161         char *tmp_path;
2162         int failures = 0;
2163
2164         printf("starting open test\n");
2165         
2166         if (!torture_open_connection(&cli1)) {
2167                 return False;
2168         }
2169         
2170         smbcli_setatr(cli1->tree, fname, 0, 0);
2171         smbcli_unlink(cli1->tree, fname);
2172         
2173         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
2174         if (fnum1 == -1) {
2175                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2176                 return False;
2177         }
2178
2179         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2180                 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
2181                 return False;
2182         }
2183         
2184         if (NT_STATUS_IS_ERR(smbcli_setatr(cli1->tree, fname, FILE_ATTRIBUTE_READONLY, 0))) {
2185                 printf("smbcli_setatr failed (%s)\n", smbcli_errstr(cli1->tree));
2186                 CHECK_MAX_FAILURES(error_test1);
2187                 return False;
2188         }
2189         
2190         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
2191         if (fnum1 == -1) {
2192                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2193                 CHECK_MAX_FAILURES(error_test1);
2194                 return False;
2195         }
2196         
2197         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
2198         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
2199         
2200         if (check_error(__location__, cli1, ERRDOS, ERRnoaccess, 
2201                         NT_STATUS_ACCESS_DENIED)) {
2202                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
2203         }
2204         
2205         printf("finished open test 1\n");
2206 error_test1:
2207         smbcli_close(cli1->tree, fnum1);
2208         
2209         /* Now try not readonly and ensure ERRbadshare is returned. */
2210         
2211         smbcli_setatr(cli1->tree, fname, 0, 0);
2212         
2213         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
2214         if (fnum1 == -1) {
2215                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2216                 return False;
2217         }
2218         
2219         /* This will fail - but the error should be ERRshare. */
2220         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
2221         
2222         if (check_error(__location__, cli1, ERRDOS, ERRbadshare, 
2223                         NT_STATUS_SHARING_VIOLATION)) {
2224                 printf("correct error code ERRDOS/ERRbadshare returned\n");
2225         }
2226         
2227         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2228                 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
2229                 return False;
2230         }
2231         
2232         smbcli_unlink(cli1->tree, fname);
2233         
2234         printf("finished open test 2\n");
2235         
2236         /* Test truncate open disposition on file opened for read. */
2237         
2238         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
2239         if (fnum1 == -1) {
2240                 printf("(3) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2241                 return False;
2242         }
2243         
2244         /* write 20 bytes. */
2245         
2246         memset(buf, '\0', 20);
2247
2248         if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
2249                 printf("write failed (%s)\n", smbcli_errstr(cli1->tree));
2250                 correct = False;
2251         }
2252
2253         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2254                 printf("(3) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
2255                 return False;
2256         }
2257         
2258         /* Ensure size == 20. */
2259         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
2260                 printf("(3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
2261                 CHECK_MAX_FAILURES(error_test3);
2262                 return False;
2263         }
2264         
2265         if (fsize != 20) {
2266                 printf("(3) file size != 20\n");
2267                 CHECK_MAX_FAILURES(error_test3);
2268                 return False;
2269         }
2270
2271         /* Now test if we can truncate a file opened for readonly. */
2272         
2273         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY|O_TRUNC, DENY_NONE);
2274         if (fnum1 == -1) {
2275                 printf("(3) open (2) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2276                 CHECK_MAX_FAILURES(error_test3);
2277                 return False;
2278         }
2279         
2280         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2281                 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
2282                 return False;
2283         }
2284
2285         /* Ensure size == 0. */
2286         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
2287                 printf("(3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
2288                 CHECK_MAX_FAILURES(error_test3);
2289                 return False;
2290         }
2291
2292         if (fsize != 0) {
2293                 printf("(3) file size != 0\n");
2294                 CHECK_MAX_FAILURES(error_test3);
2295                 return False;
2296         }
2297         printf("finished open test 3\n");
2298 error_test3:    
2299         smbcli_unlink(cli1->tree, fname);
2300
2301
2302         printf("testing ctemp\n");
2303         fnum1 = smbcli_ctemp(cli1->tree, "\\", &tmp_path);
2304         if (fnum1 == -1) {
2305                 printf("ctemp failed (%s)\n", smbcli_errstr(cli1->tree));
2306                 CHECK_MAX_FAILURES(error_test4);
2307                 return False;
2308         }
2309         printf("ctemp gave path %s\n", tmp_path);
2310         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2311                 printf("close of temp failed (%s)\n", smbcli_errstr(cli1->tree));
2312         }
2313         if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, tmp_path))) {
2314                 printf("unlink of temp failed (%s)\n", smbcli_errstr(cli1->tree));
2315         }
2316 error_test4:    
2317         /* Test the non-io opens... */
2318
2319         if (!torture_open_connection(&cli2)) {
2320                 return False;
2321         }
2322         
2323         smbcli_setatr(cli2->tree, fname, 0, 0);
2324         smbcli_unlink(cli2->tree, fname);
2325         
2326         printf("TEST #1 testing 2 non-io opens (no delete)\n");
2327         
2328         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
2329                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2330
2331         if (fnum1 == -1) {
2332                 printf("test 1 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2333                 CHECK_MAX_FAILURES(error_test10);
2334                 return False;
2335         }
2336
2337         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
2338                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
2339         if (fnum2 == -1) {
2340                 printf("test 1 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
2341                 CHECK_MAX_FAILURES(error_test10);
2342                 return False;
2343         }
2344
2345         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2346                 printf("test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2347                 return False;
2348         }
2349         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
2350                 printf("test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
2351                 return False;
2352         }
2353
2354         printf("non-io open test #1 passed.\n");
2355 error_test10:
2356         smbcli_unlink(cli1->tree, fname);
2357
2358         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
2359         
2360         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
2361                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2362
2363         if (fnum1 == -1) {
2364                 printf("test 2 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2365                 CHECK_MAX_FAILURES(error_test20);
2366                 return False;
2367         }
2368
2369         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
2370                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
2371
2372         if (fnum2 == -1) {
2373                 printf("test 2 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
2374                 CHECK_MAX_FAILURES(error_test20);
2375                 return False;
2376         }
2377
2378         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2379                 printf("test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2380                 return False;
2381         }
2382         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
2383                 printf("test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2384                 return False;
2385         }
2386
2387         printf("non-io open test #2 passed.\n");
2388 error_test20:
2389         smbcli_unlink(cli1->tree, fname);
2390
2391         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
2392         
2393         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
2394                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2395
2396         if (fnum1 == -1) {
2397                 printf("test 3 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2398                 CHECK_MAX_FAILURES(error_test30);
2399                 return False;
2400         }
2401
2402         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
2403                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
2404
2405         if (fnum2 == -1) {
2406                 printf("test 3 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
2407                 CHECK_MAX_FAILURES(error_test30);
2408                 return False;
2409         }
2410
2411         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2412                 printf("test 3 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2413                 return False;
2414         }
2415         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
2416                 printf("test 3 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
2417                 return False;
2418         }
2419
2420         printf("non-io open test #3 passed.\n");
2421 error_test30:
2422         smbcli_unlink(cli1->tree, fname);
2423
2424         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
2425         
2426         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
2427                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2428
2429         if (fnum1 == -1) {
2430                 printf("test 4 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2431                 CHECK_MAX_FAILURES(error_test40);
2432                 return False;
2433         }
2434
2435         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
2436                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
2437
2438         if (fnum2 != -1) {
2439                 printf("test 4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
2440                 CHECK_MAX_FAILURES(error_test40);
2441                 return False;
2442         }
2443
2444         printf("test 4 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
2445
2446         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2447                 printf("test 4 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2448                 return False;
2449         }
2450
2451         printf("non-io open test #4 passed.\n");
2452 error_test40:
2453         smbcli_unlink(cli1->tree, fname);
2454
2455         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
2456         
2457         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
2458                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2459
2460         if (fnum1 == -1) {
2461                 printf("test 5 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2462                 CHECK_MAX_FAILURES(error_test50);
2463                 return False;
2464         }
2465
2466         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
2467                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
2468
2469         if (fnum2 == -1) {
2470                 printf("test 5 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
2471                 CHECK_MAX_FAILURES(error_test50);
2472                 return False;
2473         }
2474
2475         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2476                 printf("test 5 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2477                 return False;
2478         }
2479
2480         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
2481                 printf("test 5 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
2482                 return False;
2483         }
2484
2485         printf("non-io open test #5 passed.\n");
2486 error_test50:
2487         printf("TEST #6 testing 1 non-io open, one io open\n");
2488         
2489         smbcli_unlink(cli1->tree, fname);
2490
2491         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
2492                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2493
2494         if (fnum1 == -1) {
2495                 printf("test 6 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2496                 CHECK_MAX_FAILURES(error_test60);
2497                 return False;
2498         }
2499
2500         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
2501                                    NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OPEN_IF, 0, 0);
2502
2503         if (fnum2 == -1) {
2504                 printf("test 6 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
2505                 CHECK_MAX_FAILURES(error_test60);
2506                 return False;
2507         }
2508
2509         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2510                 printf("test 6 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2511                 return False;
2512         }
2513
2514         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
2515                 printf("test 6 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
2516                 return False;
2517         }
2518
2519         printf("non-io open test #6 passed.\n");
2520 error_test60:
2521         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
2522
2523         smbcli_unlink(cli1->tree, fname);
2524
2525         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
2526                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2527
2528         if (fnum1 == -1) {
2529                 printf("test 7 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2530                 CHECK_MAX_FAILURES(error_test70);
2531                 return False;
2532         }
2533
2534         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
2535                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
2536
2537         if (fnum2 != -1) {
2538                 printf("test 7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
2539                 CHECK_MAX_FAILURES(error_test70);
2540                 return False;
2541         }
2542
2543         printf("test 7 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
2544
2545         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2546                 printf("test 7 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2547                 return False;
2548         }
2549
2550         printf("non-io open test #7 passed.\n");
2551
2552 error_test70:
2553
2554         printf("TEST #8 testing one normal open, followed by lock, followed by open with truncate\n");
2555
2556         smbcli_unlink(cli1->tree, fname);
2557
2558         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2559         if (fnum1 == -1) {
2560                 printf("(8) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2561                 return False;
2562         }
2563         
2564         /* write 20 bytes. */
2565         
2566         memset(buf, '\0', 20);
2567
2568         if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
2569                 printf("(8) write failed (%s)\n", smbcli_errstr(cli1->tree));
2570                 correct = False;
2571         }
2572
2573         /* Ensure size == 20. */
2574         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
2575                 printf("(8) getatr (1) failed (%s)\n", smbcli_errstr(cli1->tree));
2576                 CHECK_MAX_FAILURES(error_test80);
2577                 return False;
2578         }
2579         
2580         if (fsize != 20) {
2581                 printf("(8) file size != 20\n");
2582                 CHECK_MAX_FAILURES(error_test80);
2583                 return False;
2584         }
2585
2586         /* Get an exclusive lock on the open file. */
2587         if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
2588                 printf("(8) lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
2589                 CHECK_MAX_FAILURES(error_test80);
2590                 return False;
2591         }
2592
2593         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
2594         if (fnum1 == -1) {
2595                 printf("(8) open (2) of %s with truncate failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2596                 return False;
2597         }
2598
2599         /* Ensure size == 0. */
2600         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
2601                 printf("(8) getatr (2) failed (%s)\n", smbcli_errstr(cli1->tree));
2602                 CHECK_MAX_FAILURES(error_test80);
2603                 return False;
2604         }
2605         
2606         if (fsize != 0) {
2607                 printf("(8) file size != 0\n");
2608                 CHECK_MAX_FAILURES(error_test80);
2609                 return False;
2610         }
2611
2612         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2613                 printf("(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
2614                 return False;
2615         }
2616         
2617         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
2618                 printf("(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
2619                 return False;
2620         }
2621         
2622 error_test80:
2623
2624         printf("open test #8 passed.\n");
2625
2626         smbcli_unlink(cli1->tree, fname);
2627
2628         if (!torture_close_connection(cli1)) {
2629                 correct = False;
2630         }
2631         if (!torture_close_connection(cli2)) {
2632                 correct = False;
2633         }
2634         
2635         return correct;
2636 }
2637
2638
2639 static uint32_t open_attrs_table[] = {
2640                 FILE_ATTRIBUTE_NORMAL,
2641                 FILE_ATTRIBUTE_ARCHIVE,
2642                 FILE_ATTRIBUTE_READONLY,
2643                 FILE_ATTRIBUTE_HIDDEN,
2644                 FILE_ATTRIBUTE_SYSTEM,
2645
2646                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
2647                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
2648                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
2649                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
2650                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
2651                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
2652
2653                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
2654                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
2655                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
2656                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
2657 };
2658
2659 struct trunc_open_results {
2660         uint_t num;
2661         uint32_t init_attr;
2662         uint32_t trunc_attr;
2663         uint32_t result_attr;
2664 };
2665
2666 static struct trunc_open_results attr_results[] = {
2667         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
2668         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
2669         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
2670         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
2671         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
2672         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
2673         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
2674         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
2675         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
2676         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
2677         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
2678         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
2679         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
2680         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
2681         { 104, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
2682         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
2683         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
2684         { 121, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
2685         { 170, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN },
2686         { 173, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM },
2687         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
2688         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
2689         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
2690         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
2691         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
2692         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
2693 };
2694
2695 static BOOL run_openattrtest(int dummy)
2696 {
2697         struct smbcli_state *cli1;
2698         const char *fname = "\\openattr.file";
2699         int fnum1;
2700         BOOL correct = True;
2701         uint16_t attr;
2702         uint_t i, j, k, l;
2703         int failures = 0;
2704
2705         printf("starting open attr test\n");
2706         
2707         if (!torture_open_connection(&cli1)) {
2708                 return False;
2709         }
2710         
2711         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
2712                 smbcli_setatr(cli1->tree, fname, 0, 0);
2713                 smbcli_unlink(cli1->tree, fname);
2714                 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_WRITE_DATA, open_attrs_table[i],
2715                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2716
2717                 if (fnum1 == -1) {
2718                         printf("open %d (1) of %s failed (%s)\n", i, fname, smbcli_errstr(cli1->tree));
2719                         return False;
2720                 }
2721
2722                 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2723                         printf("close %d (1) of %s failed (%s)\n", i, fname, smbcli_errstr(cli1->tree));
2724                         return False;
2725                 }
2726
2727                 for (j = 0; j < ARRAY_SIZE(open_attrs_table); j++) {
2728                         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
2729                                                    SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA, 
2730                                                    open_attrs_table[j],
2731                                                    NTCREATEX_SHARE_ACCESS_NONE, 
2732                                                    NTCREATEX_DISP_OVERWRITE, 0, 0);
2733
2734                         if (fnum1 == -1) {
2735                                 for (l = 0; l < ARRAY_SIZE(attr_results); l++) {
2736                                         if (attr_results[l].num == k) {
2737                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
2738                                                                 k, open_attrs_table[i],
2739                                                                 open_attrs_table[j],
2740                                                                 fname, NT_STATUS_V(smbcli_nt_error(cli1->tree)), smbcli_errstr(cli1->tree));
2741                                                 correct = False;
2742                                                 CHECK_MAX_FAILURES(error_exit);
2743                                         }
2744                                 }
2745                                 if (NT_STATUS_V(smbcli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) {
2746                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
2747                                                         k, open_attrs_table[i], open_attrs_table[j],
2748                                                         smbcli_errstr(cli1->tree));
2749                                         correct = False;
2750                                         CHECK_MAX_FAILURES(error_exit);
2751                                 }
2752 #if 0
2753                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
2754 #endif
2755                                 k++;
2756                                 continue;
2757                         }
2758
2759                         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2760                                 printf("close %d (2) of %s failed (%s)\n", j, fname, smbcli_errstr(cli1->tree));
2761                                 return False;
2762                         }
2763
2764                         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, &attr, NULL, NULL))) {
2765                                 printf("getatr(2) failed (%s)\n", smbcli_errstr(cli1->tree));
2766                                 return False;
2767                         }
2768
2769 #if 0
2770                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
2771                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
2772 #endif
2773
2774                         for (l = 0; l < ARRAY_SIZE(attr_results); l++) {
2775                                 if (attr_results[l].num == k) {
2776                                         if (attr != attr_results[l].result_attr ||
2777                                                         open_attrs_table[i] != attr_results[l].init_attr ||
2778                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
2779                                                 printf("[%d] getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
2780                                                         k, open_attrs_table[i],
2781                                                         open_attrs_table[j],
2782                                                         (uint_t)attr,
2783                                                         attr_results[l].result_attr);
2784                                                 correct = False;
2785                                                 CHECK_MAX_FAILURES(error_exit);
2786                                         }
2787                                         break;
2788                                 }
2789                         }
2790                         k++;
2791                 }
2792         }
2793 error_exit:
2794         smbcli_setatr(cli1->tree, fname, 0, 0);
2795         smbcli_unlink(cli1->tree, fname);
2796
2797         printf("open attr test %s.\n", correct ? "passed" : "failed");
2798
2799         if (!torture_close_connection(cli1)) {
2800                 correct = False;
2801         }
2802         return correct;
2803 }
2804
2805 static void list_fn(file_info *finfo, const char *name, void *state)
2806 {
2807         
2808 }
2809
2810 /*
2811   test directory listing speed
2812  */
2813 static BOOL run_dirtest(int dummy)
2814 {
2815         int i;
2816         struct smbcli_state *cli;
2817         int fnum;
2818         double t1;
2819         BOOL correct = True;
2820
2821         printf("starting directory test\n");
2822
2823         if (!torture_open_connection(&cli)) {
2824                 return False;
2825         }
2826
2827         printf("Creating %d random filenames\n", torture_numops);
2828
2829         srandom(0);
2830         for (i=0;i<torture_numops;i++) {
2831                 char *fname;
2832                 asprintf(&fname, "\\%x", (int)random());
2833                 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2834                 if (fnum == -1) {
2835                         fprintf(stderr,"Failed to open %s\n", fname);
2836                         return False;
2837                 }
2838                 smbcli_close(cli->tree, fnum);
2839                 free(fname);
2840         }
2841
2842         t1 = end_timer();
2843
2844         printf("Matched %d\n", smbcli_list(cli->tree, "a*.*", 0, list_fn, NULL));
2845         printf("Matched %d\n", smbcli_list(cli->tree, "b*.*", 0, list_fn, NULL));
2846         printf("Matched %d\n", smbcli_list(cli->tree, "xyzabc", 0, list_fn, NULL));
2847
2848         printf("dirtest core %g seconds\n", end_timer() - t1);
2849
2850         srandom(0);
2851         for (i=0;i<torture_numops;i++) {
2852                 char *fname;
2853                 asprintf(&fname, "\\%x", (int)random());
2854                 smbcli_unlink(cli->tree, fname);
2855                 free(fname);
2856         }
2857
2858         if (!torture_close_connection(cli)) {
2859                 correct = False;
2860         }
2861
2862         printf("finished dirtest\n");
2863
2864         return correct;
2865 }
2866
2867 /*
2868   sees what IOCTLs are supported
2869  */
2870 BOOL torture_ioctl_test(int dummy)
2871 {
2872         struct smbcli_state *cli;
2873         uint16_t device, function;
2874         int fnum;
2875         const char *fname = "\\ioctl.dat";
2876         NTSTATUS status;
2877         union smb_ioctl parms;
2878         TALLOC_CTX *mem_ctx;
2879
2880         if (!torture_open_connection(&cli)) {
2881                 return False;
2882         }
2883
2884         mem_ctx = talloc_init("ioctl_test");
2885
2886         printf("starting ioctl test\n");
2887
2888         smbcli_unlink(cli->tree, fname);
2889
2890         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
2891         if (fnum == -1) {
2892                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
2893                 return False;
2894         }
2895
2896         parms.ioctl.level = RAW_IOCTL_IOCTL;
2897         parms.ioctl.in.fnum = fnum;
2898         parms.ioctl.in.request = IOCTL_QUERY_JOB_INFO;
2899         status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
2900         printf("ioctl job info: %s\n", smbcli_errstr(cli->tree));
2901
2902         for (device=0;device<0x100;device++) {
2903                 printf("testing device=0x%x\n", device);
2904                 for (function=0;function<0x100;function++) {
2905                         parms.ioctl.in.request = (device << 16) | function;
2906                         status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
2907
2908                         if (NT_STATUS_IS_OK(status)) {
2909                                 printf("ioctl device=0x%x function=0x%x OK : %d bytes\n", 
2910                                         device, function, parms.ioctl.out.blob.length);
2911                         }
2912                 }
2913         }
2914
2915         if (!torture_close_connection(cli)) {
2916                 return False;
2917         }
2918
2919         return True;
2920 }
2921
2922
2923 /*
2924   tries variants of chkpath
2925  */
2926 BOOL torture_chkpath_test(int dummy)
2927 {
2928         struct smbcli_state *cli;
2929         int fnum;
2930         BOOL ret;
2931
2932         if (!torture_open_connection(&cli)) {
2933                 return False;
2934         }
2935
2936         printf("starting chkpath test\n");
2937
2938         printf("Testing valid and invalid paths\n");
2939
2940         /* cleanup from an old run */
2941         smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
2942         smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
2943         smbcli_rmdir(cli->tree, "\\chkpath.dir");
2944
2945         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir"))) {
2946                 printf("mkdir1 failed : %s\n", smbcli_errstr(cli->tree));
2947                 return False;
2948         }
2949
2950         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir\\dir2"))) {
2951                 printf("mkdir2 failed : %s\n", smbcli_errstr(cli->tree));
2952                 return False;
2953         }
2954
2955         fnum = smbcli_open(cli->tree, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
2956         if (fnum == -1) {
2957                 printf("open1 failed (%s)\n", smbcli_errstr(cli->tree));
2958                 return False;
2959         }
2960         smbcli_close(cli->tree, fnum);
2961
2962         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir"))) {
2963                 printf("chkpath1 failed: %s\n", smbcli_errstr(cli->tree));
2964                 ret = False;
2965         }
2966
2967         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dir2"))) {
2968                 printf("chkpath2 failed: %s\n", smbcli_errstr(cli->tree));
2969                 ret = False;
2970         }
2971
2972         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\foo.txt"))) {
2973                 ret = check_error(__location__, cli, ERRDOS, ERRbadpath, 
2974                                   NT_STATUS_NOT_A_DIRECTORY);
2975         } else {
2976                 printf("* chkpath on a file should fail\n");
2977                 ret = False;
2978         }
2979
2980         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\bar.txt"))) {
2981                 ret = check_error(__location__, cli, ERRDOS, ERRbadfile, 
2982                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
2983         } else {
2984                 printf("* chkpath on a non existent file should fail\n");
2985                 ret = False;
2986         }
2987
2988         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dirxx\\bar.txt"))) {
2989                 ret = check_error(__location__, cli, ERRDOS, ERRbadpath, 
2990                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
2991         } else {
2992                 printf("* chkpath on a non existent component should fail\n");
2993                 ret = False;
2994         }
2995
2996         smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
2997         smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
2998         smbcli_rmdir(cli->tree, "\\chkpath.dir");
2999
3000         if (!torture_close_connection(cli)) {
3001                 return False;
3002         }
3003
3004         return ret;
3005 }
3006
3007 static BOOL run_dirtest1(int dummy)
3008 {
3009         int i;
3010         struct smbcli_state *cli;
3011         int fnum, num_seen;
3012         BOOL correct = True;
3013
3014         printf("starting directory test\n");
3015
3016         if (!torture_open_connection(&cli)) {
3017                 return False;
3018         }
3019
3020         if (smbcli_deltree(cli->tree, "\\LISTDIR") == -1) {
3021                 fprintf(stderr,"Failed to deltree %s, error=%s\n", "\\LISTDIR", smbcli_errstr(cli->tree));
3022                 return False;
3023         }
3024         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\LISTDIR"))) {
3025                 fprintf(stderr,"Failed to mkdir %s, error=%s\n", "\\LISTDIR", smbcli_errstr(cli->tree));
3026                 return False;
3027         }
3028
3029         printf("Creating %d files\n", torture_entries);
3030
3031         /* Create torture_entries files and torture_entries directories. */
3032         for (i=0;i<torture_entries;i++) {
3033                 char *fname;
3034                 asprintf(&fname, "\\LISTDIR\\f%d", i);
3035                 fnum = smbcli_nt_create_full(cli->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
3036                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3037                 if (fnum == -1) {
3038                         fprintf(stderr,"Failed to open %s, error=%s\n", fname, smbcli_errstr(cli->tree));
3039                         return False;
3040                 }
3041                 free(fname);
3042                 smbcli_close(cli->tree, fnum);
3043         }
3044         for (i=0;i<torture_entries;i++) {
3045                 char *fname;
3046                 asprintf(&fname, "\\LISTDIR\\d%d", i);
3047                 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, fname))) {
3048                         fprintf(stderr,"Failed to open %s, error=%s\n", fname, smbcli_errstr(cli->tree));
3049                         return False;
3050                 }
3051                 free(fname);
3052         }
3053
3054         /* Now ensure that doing an old list sees both files and directories. */
3055         num_seen = smbcli_list_old(cli->tree, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, NULL);
3056         printf("num_seen = %d\n", num_seen );
3057         /* We should see (torture_entries) each of files & directories + . and .. */
3058         if (num_seen != (2*torture_entries)+2) {
3059                 correct = False;
3060                 fprintf(stderr,"entry count mismatch, should be %d, was %d\n",
3061                         (2*torture_entries)+2, num_seen);
3062         }
3063                 
3064
3065         /* Ensure if we have the "must have" bits we only see the
3066          * relevant entries.
3067          */
3068         num_seen = smbcli_list_old(cli->tree, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, NULL);
3069         printf("num_seen = %d\n", num_seen );
3070         if (num_seen != torture_entries+2) {
3071                 correct = False;
3072                 fprintf(stderr,"entry count mismatch, should be %d, was %d\n",
3073                         torture_entries+2, num_seen);
3074         }
3075
3076         num_seen = smbcli_list_old(cli->tree, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, NULL);
3077         printf("num_seen = %d\n", num_seen );
3078         if (num_seen != torture_entries) {
3079                 correct = False;
3080                 fprintf(stderr,"entry count mismatch, should be %d, was %d\n",
3081                         torture_entries, num_seen);
3082         }
3083
3084         /* Delete everything. */
3085         if (smbcli_deltree(cli->tree, "\\LISTDIR") == -1) {
3086                 fprintf(stderr,"Failed to deltree %s, error=%s\n", "\\LISTDIR", smbcli_errstr(cli->tree));
3087                 return False;
3088         }
3089
3090 #if 0
3091         printf("Matched %d\n", smbcli_list(cli->tree, "a*.*", 0, list_fn, NULL));
3092         printf("Matched %d\n", smbcli_list(cli->tree, "b*.*", 0, list_fn, NULL));
3093         printf("Matched %d\n", smbcli_list(cli->tree, "xyzabc", 0, list_fn, NULL));
3094 #endif
3095
3096         if (!torture_close_connection(cli)) {
3097                 correct = False;
3098         }
3099
3100         printf("finished dirtest1\n");
3101
3102         return correct;
3103 }
3104
3105
3106 /*
3107    simple test harness for playing with deny modes
3108  */
3109 static BOOL run_deny3test(int dummy)
3110 {
3111         struct smbcli_state *cli1, *cli2;
3112         int fnum1, fnum2;
3113         const char *fname;
3114
3115         printf("starting deny3 test\n");
3116
3117         printf("Testing simple deny modes\n");
3118         
3119         if (!torture_open_connection(&cli1)) {
3120                 return False;
3121         }
3122         if (!torture_open_connection(&cli2)) {
3123                 return False;
3124         }
3125
3126         fname = "\\deny_dos1.dat";
3127
3128         smbcli_unlink(cli1->tree, fname);
3129         fnum1 = smbcli_open(cli1->tree, fname, O_CREAT|O_TRUNC|O_WRONLY, DENY_DOS);
3130         fnum2 = smbcli_open(cli1->tree, fname, O_CREAT|O_TRUNC|O_WRONLY, DENY_DOS);
3131         if (fnum1 != -1) smbcli_close(cli1->tree, fnum1);
3132         if (fnum2 != -1) smbcli_close(cli1->tree, fnum2);
3133         smbcli_unlink(cli1->tree, fname);
3134         printf("fnum1=%d fnum2=%d\n", fnum1, fnum2);
3135
3136
3137         fname = "\\deny_dos2.dat";
3138
3139         smbcli_unlink(cli1->tree, fname);
3140         fnum1 = smbcli_open(cli1->tree, fname, O_CREAT|O_TRUNC|O_WRONLY, DENY_DOS);
3141         fnum2 = smbcli_open(cli2->tree, fname, O_CREAT|O_TRUNC|O_WRONLY, DENY_DOS);
3142         if (fnum1 != -1) smbcli_close(cli1->tree, fnum1);
3143         if (fnum2 != -1) smbcli_close(cli2->tree, fnum2);
3144         smbcli_unlink(cli1->tree, fname);
3145         printf("fnum1=%d fnum2=%d\n", fnum1, fnum2);
3146
3147
3148         torture_close_connection(cli1);
3149         torture_close_connection(cli2);
3150
3151         return True;
3152 }
3153
3154 /*
3155   parse a //server/share type UNC name
3156 */
3157 static BOOL parse_unc(const char *unc_name, char **hostname, char **sharename)
3158 {
3159         char *p;
3160
3161         if (strncmp(unc_name, "//", 2)) {
3162                 return False;
3163         }
3164
3165         *hostname = strdup(&unc_name[2]);
3166         p = strchr_m(&(*hostname)[2],'/');
3167         if (!p) {
3168                 return False;
3169         }
3170         *p = 0;
3171         *sharename = strdup(p+1);
3172
3173         return True;
3174 }
3175
3176
3177
3178 static void sigcont(void)
3179 {
3180 }
3181
3182 double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result)
3183 {
3184         int i, status;
3185         volatile pid_t *child_status;
3186         volatile BOOL *child_status_out;
3187         int synccount;
3188         int tries = 8;
3189         double start_time_limit = 10 + (torture_nprocs * 1.5);
3190         char **unc_list = NULL;
3191         const char *p;
3192         int num_unc_names = 0;
3193
3194         synccount = 0;
3195
3196         signal(SIGCONT, sigcont);
3197
3198         child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*torture_nprocs);
3199         if (!child_status) {
3200                 printf("Failed to setup shared memory\n");
3201                 return -1;
3202         }
3203
3204         child_status_out = (volatile BOOL *)shm_setup(sizeof(BOOL)*torture_nprocs);
3205         if (!child_status_out) {
3206                 printf("Failed to setup result status shared memory\n");
3207                 return -1;
3208         }
3209
3210         p = lp_parm_string(-1, "torture", "unclist");
3211         if (p) {
3212                 unc_list = file_lines_load(p, &num_unc_names);
3213                 if (!unc_list || num_unc_names <= 0) {
3214                         printf("Failed to load unc names list from '%s'\n", p);
3215                         exit(1);
3216                 }
3217         }
3218
3219         for (i = 0; i < torture_nprocs; i++) {
3220                 child_status[i] = 0;
3221                 child_status_out[i] = True;
3222         }
3223
3224         start_timer();
3225
3226         for (i=0;i<torture_nprocs;i++) {
3227                 procnum = i;
3228                 if (fork() == 0) {
3229                         char *myname;
3230                         char *hostname=NULL, *sharename;
3231
3232                         pid_t mypid = getpid();
3233                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
3234
3235                         asprintf(&myname, "CLIENT%d", i);
3236                         lp_set_cmdline("netbios name", myname);
3237                         free(myname);
3238
3239
3240                         if (unc_list) {
3241                                 if (!parse_unc(unc_list[i % num_unc_names],
3242                                                &hostname, &sharename)) {
3243                                         printf("Failed to parse UNC name %s\n",
3244                                                unc_list[i % num_unc_names]);
3245                                         exit(1);
3246                                 }
3247                         }
3248
3249                         while (1) {
3250                                 if (hostname) {
3251                                         if (torture_open_connection_share(&current_cli,
3252                                                                           hostname, 
3253                                                                           sharename)) {
3254                                                 break;
3255                                         }
3256                                 } else if (torture_open_connection(&current_cli)) {
3257                                                 break;
3258                                 }
3259                                 if (tries-- == 0) {
3260                                         printf("pid %d failed to start\n", (int)getpid());
3261                                         _exit(1);
3262                                 }
3263                                 msleep(100);    
3264                         }
3265
3266                         child_status[i] = getpid();
3267
3268                         pause();
3269
3270                         if (child_status[i]) {
3271                                 printf("Child %d failed to start!\n", i);
3272                                 child_status_out[i] = 1;
3273                                 _exit(1);
3274                         }
3275
3276                         child_status_out[i] = fn(current_cli, i);
3277                         _exit(0);
3278                 }
3279         }
3280
3281         do {
3282                 synccount = 0;
3283                 for (i=0;i<torture_nprocs;i++) {
3284                         if (child_status[i]) synccount++;
3285                 }
3286                 if (synccount == torture_nprocs) break;
3287                 msleep(100);
3288         } while (end_timer() < start_time_limit);
3289
3290         if (synccount != torture_nprocs) {
3291                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
3292                 *result = False;
3293                 return end_timer();
3294         }
3295
3296         printf("Starting %d clients\n", torture_nprocs);
3297
3298         /* start the client load */
3299         start_timer();
3300         for (i=0;i<torture_nprocs;i++) {
3301                 child_status[i] = 0;
3302         }
3303         kill(0, SIGCONT);
3304
3305         printf("%d clients started\n", torture_nprocs);
3306
3307         for (i=0;i<torture_nprocs;i++) {
3308                 int ret;
3309                 while ((ret=waitpid(0, &status, 0)) == -1 && errno == EINTR) /* noop */ ;
3310                 if (ret == -1 || WEXITSTATUS(status) != 0) {
3311                         *result = False;
3312                 }
3313         }
3314
3315         printf("\n");
3316         
3317         for (i=0;i<torture_nprocs;i++) {
3318                 if (!child_status_out[i]) {
3319                         *result = False;
3320                 }
3321         }
3322         return end_timer();
3323 }
3324
3325 #define FLAG_MULTIPROC 1
3326
3327 static struct {
3328         const char *name;
3329         BOOL (*fn)(int);
3330         uint_t flags;
3331 } torture_ops[] = {
3332         /* base tests */
3333         {"BASE-FDPASS", run_fdpasstest, 0},
3334         {"BASE-LOCK1",  torture_locktest1,  0},
3335         {"BASE-LOCK2",  torture_locktest2,  0},
3336         {"BASE-LOCK3",  torture_locktest3,  0},
3337         {"BASE-LOCK4",  torture_locktest4,  0},
3338         {"BASE-LOCK5",  torture_locktest5,  0},
3339         {"BASE-LOCK6",  torture_locktest6,  0},
3340         {"BASE-LOCK7",  torture_locktest7,  0},
3341         {"BASE-UNLINK", run_unlinktest, 0},
3342         {"BASE-ATTR",   run_attrtest,   0},
3343         {"BASE-TRANS2", run_trans2test, 0},
3344         {"BASE-NEGNOWAIT", run_negprot_nowait, 0},
3345         {"BASE-DIR",  run_dirtest, 0},
3346         {"BASE-DIR1",  run_dirtest1, 0},
3347         {"BASE-DENY1",  torture_denytest1, 0},
3348         {"BASE-DENY2",  torture_denytest2, 0},
3349         {"BASE-TCON",  run_tcon_test, 0},
3350         {"BASE-TCONDEV",  run_tcon_devtype_test, 0},
3351         {"BASE-VUID", run_vuidtest, 0},
3352         {"BASE-RW1",  run_readwritetest, 0},
3353         {"BASE-RW2",  run_readwritemulti, FLAG_MULTIPROC},
3354         {"BASE-OPEN", run_opentest, 0},
3355         {"BASE-DENY3", run_deny3test, 0},
3356         {"BASE-DEFER_OPEN", run_deferopen, FLAG_MULTIPROC},
3357         {"BASE-XCOPY", run_xcopy, 0},
3358         {"BASE-RENAME", run_rename, 0},
3359         {"BASE-DELETE", run_deletetest, 0},
3360         {"BASE-PROPERTIES", run_properties, 0},
3361         {"BASE-MANGLE", torture_mangle, 0},
3362         {"BASE-OPENATTR", run_openattrtest, 0},
3363         {"BASE-CHARSET", torture_charset, 0},
3364         {"BASE-CHKPATH",  torture_chkpath_test, 0},
3365         {"BASE-SECLEAK",  torture_sec_leak, 0},
3366
3367         /* benchmarking tests */
3368         {"BENCH-HOLDCON",  torture_holdcon, 0},
3369         {"BENCH-NBENCH",  torture_nbench, 0},
3370         {"BENCH-TORTURE",run_torture,    FLAG_MULTIPROC},
3371
3372         /* RAW smb tests */
3373         {"RAW-QFSINFO", torture_raw_qfsinfo, 0},
3374         {"RAW-QFILEINFO", torture_raw_qfileinfo, 0},
3375         {"RAW-SFILEINFO", torture_raw_sfileinfo, 0},
3376         {"RAW-SFILEINFO-BUG", torture_raw_sfileinfo_bug, 0},
3377         {"RAW-SEARCH", torture_raw_search, 0},
3378         {"RAW-CLOSE", torture_raw_close, 0},
3379         {"RAW-OPEN", torture_raw_open, 0},
3380         {"RAW-MKDIR", torture_raw_mkdir, 0},
3381         {"RAW-OPLOCK", torture_raw_oplock, 0},
3382         {"RAW-NOTIFY", torture_raw_notify, 0},
3383         {"RAW-MUX", torture_raw_mux, 0},
3384         {"RAW-IOCTL", torture_raw_ioctl, 0},
3385         {"RAW-CHKPATH", torture_raw_chkpath, 0},
3386         {"RAW-UNLINK", torture_raw_unlink, 0},
3387         {"RAW-READ", torture_raw_read, 0},
3388         {"RAW-WRITE", torture_raw_write, 0},
3389         {"RAW-LOCK", torture_raw_lock, 0},
3390         {"RAW-CONTEXT", torture_raw_context, 0},
3391         {"RAW-RENAME", torture_raw_rename, 0},
3392         {"RAW-SEEK", torture_raw_seek, 0},
3393         {"RAW-RAP", torture_raw_rap, 0},
3394
3395         /* protocol scanners */
3396         {"SCAN-TRANS2", torture_trans2_scan, 0},
3397         {"SCAN-NTTRANS", torture_nttrans_scan, 0},
3398         {"SCAN-ALIASES", torture_trans2_aliases, 0},
3399         {"SCAN-SMB", torture_smb_scan, 0},
3400         {"SCAN-MAXFID", run_maxfidtest, FLAG_MULTIPROC},
3401         {"SCAN-UTABLE", torture_utable, 0},
3402         {"SCAN-CASETABLE", torture_casetable, 0},
3403         {"SCAN-PIPE_NUMBER", run_pipe_number, 0},
3404         {"SCAN-IOCTL",  torture_ioctl_test, 0},
3405
3406         /* rpc testers */
3407         {"RPC-LSA", torture_rpc_lsa, 0},
3408         {"RPC-ECHO", torture_rpc_echo, 0},
3409         {"RPC-DFS", torture_rpc_dfs, 0},
3410         {"RPC-SPOOLSS", torture_rpc_spoolss, 0},
3411         {"RPC-SAMR", torture_rpc_samr, 0},
3412         {"RPC-NETLOGON", torture_rpc_netlogon, 0},
3413         {"RPC-SCHANNEL", torture_rpc_schannel, 0},
3414         {"RPC-WKSSVC", torture_rpc_wkssvc, 0},
3415         {"RPC-SRVSVC", torture_rpc_srvsvc, 0},
3416         {"RPC-SVCCTL", torture_rpc_svcctl, 0},
3417         {"RPC-ATSVC", torture_rpc_atsvc, 0},
3418         {"RPC-EVENTLOG", torture_rpc_eventlog, 0},
3419         {"RPC-EPMAPPER", torture_rpc_epmapper, 0},
3420         {"RPC-WINREG", torture_rpc_winreg, 0},
3421         {"RPC-OXIDRESOLVE", torture_rpc_oxidresolve, 0},
3422         {"RPC-MGMT", torture_rpc_mgmt, 0},
3423         {"RPC-SCANNER", torture_rpc_scanner, 0},
3424         {"RPC-AUTOIDL", torture_rpc_autoidl, 0},
3425         {"RPC-COUNTCALLS", torture_rpc_countcalls, 0},
3426         {"RPC-MULTIBIND", torture_multi_bind, 0},
3427         {"RPC-DRSUAPI", torture_rpc_drsuapi, 0},
3428
3429         /* local (no server) testers */
3430         {"LOCAL-NTLMSSP", torture_ntlmssp_self_check, 0},
3431         {"LOCAL-ICONV", torture_local_iconv, 0},
3432         {"LOCAL-TALLOC", torture_local_talloc, 0},
3433         {"LOCAL-MESSAGING", torture_local_messaging, 0},
3434
3435         /* ldap testers */
3436         {"LDAP-BASIC", torture_ldap_basic, 0},
3437
3438         {NULL, NULL, 0}};
3439
3440
3441
3442 /****************************************************************************
3443 run a specified test or "ALL"
3444 ****************************************************************************/
3445 static BOOL run_test(const char *name)
3446 {
3447         BOOL ret = True;
3448         int i;
3449         BOOL matched = False;
3450
3451         if (strequal(name,"ALL")) {
3452                 for (i=0;torture_ops[i].name;i++) {
3453                         if (!run_test(torture_ops[i].name)) {
3454                                 ret = False;
3455                         }
3456                 }
3457                 return ret;
3458         }
3459
3460         for (i=0;torture_ops[i].name;i++) {
3461                 if (gen_fnmatch(name, torture_ops[i].name) == 0) {
3462                         double t;
3463                         matched = True;
3464                         init_iconv();
3465                         printf("Running %s\n", torture_ops[i].name);
3466                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
3467                                 BOOL result;
3468                                 t = torture_create_procs(torture_ops[i].fn, &result);
3469                                 if (!result) { 
3470                                         ret = False;
3471                                         printf("TEST %s FAILED!\n", torture_ops[i].name);
3472                                 }
3473                                          
3474                         } else {
3475                                 start_timer();
3476                                 if (!torture_ops[i].fn(0)) {
3477                                         ret = False;
3478                                         printf("TEST %s FAILED!\n", torture_ops[i].name);
3479                                 }
3480                                 t = end_timer();
3481                         }
3482                         printf("%s took %g secs\n\n", torture_ops[i].name, t);
3483                 }
3484         }
3485
3486         if (!matched) {
3487                 printf("Unknown torture operation '%s'\n", name);
3488         }
3489
3490         return ret;
3491 }
3492
3493
3494 static void parse_dns(const char *dns)
3495 {
3496         char *userdn, *basedn, *secret;
3497         char *p, *d;
3498
3499         /* retrievieng the userdn */
3500         p = strchr_m(dns, '#');
3501         if (!p) {
3502                 lp_set_cmdline("torture:ldap_userdn", "");
3503                 lp_set_cmdline("torture:ldap_basedn", "");
3504                 lp_set_cmdline("torture:ldap_secret", "");
3505                 return;
3506         }
3507         userdn = strndup(dns, p - dns);
3508         lp_set_cmdline("torture:ldap_userdn", userdn);
3509
3510         /* retrieve the basedn */
3511         d = p + 1;
3512         p = strchr_m(d, '#');
3513         if (!p) {
3514                 lp_set_cmdline("torture:ldap_basedn", "");
3515                 lp_set_cmdline("torture:ldap_secret", "");
3516                 return;
3517         }
3518         basedn = strndup(d, p - d);
3519         lp_set_cmdline("torture:ldap_basedn", basedn);
3520
3521         /* retrieve the secret */
3522         p = p + 1;
3523         if (!p) {
3524                 lp_set_cmdline("torture:ldap_secret", "");
3525                 return;
3526         }
3527         secret = strdup(p);
3528         lp_set_cmdline("torture:ldap_secret", secret);
3529
3530         printf ("%s - %s - %s\n", userdn, basedn, secret);
3531
3532 }
3533
3534 static void usage(poptContext pc)
3535 {
3536         int i;
3537         int perline = 5;
3538
3539         poptPrintUsage(pc, stdout, 0);
3540         printf("\n");
3541
3542         printf("tests are:");
3543         for (i=0;torture_ops[i].name;i++) {
3544                 if ((i%perline)==0) {
3545                         printf("\n");
3546                 }
3547                 printf("%s ", torture_ops[i].name);
3548         }
3549         printf("\n\n");
3550
3551         printf("default test is ALL\n");
3552         
3553         exit(1);
3554 }
3555
3556 /****************************************************************************
3557   main program
3558 ****************************************************************************/
3559  int main(int argc,char *argv[])
3560 {
3561         int opt, i;
3562         char *p;
3563         BOOL correct = True;
3564         int argc_new;
3565         char **argv_new;
3566         poptContext pc;
3567         enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS,OPT_DANGEROUS};
3568         struct poptOption long_options[] = {
3569                 POPT_AUTOHELP
3570                 {"smb-ports",   'p', POPT_ARG_STRING, NULL,             0,      "SMB ports",    NULL},
3571                 {"seed",          0, POPT_ARG_STRING, NULL,             0,      "seed",         NULL},
3572                 {"num-progs",     0, POPT_ARG_INT,  &torture_nprocs,    0,      "num progs",    NULL},
3573                 {"num-ops",       0, POPT_ARG_INT,  &torture_numops,    0,      "num ops",      NULL},
3574                 {"entries",       0, POPT_ARG_INT,  &torture_entries,   0,      "entries",      NULL},
3575                 {"use-oplocks", 'L', POPT_ARG_NONE, &use_oplocks,       0,      "use oplocks",  NULL},
3576                 {"show-all",      0, POPT_ARG_NONE, &torture_showall,   0,      "show all",     NULL},
3577                 {"loadfile",      0, POPT_ARG_STRING,   NULL,   OPT_LOADFILE,   "loadfile",     NULL},
3578                 {"unclist",       0, POPT_ARG_STRING,   NULL,   OPT_UNCLIST,    "unclist",      NULL},
3579                 {"timelimit",   't', POPT_ARG_STRING,   NULL,   OPT_TIMELIMIT,  "timelimit",    NULL},
3580                 {"failures",    'f', POPT_ARG_INT,  &torture_failures,  0,      "failures",     NULL},
3581                 {"parse-dns",   'D', POPT_ARG_STRING,   NULL,   OPT_DNS,        "parse-dns",    NULL},
3582                 {"dangerous",   'X', POPT_ARG_NONE,     NULL,   OPT_DANGEROUS,  "dangerous",    NULL},
3583                 POPT_COMMON_SAMBA
3584                 POPT_COMMON_CONNECTION
3585                 POPT_COMMON_CREDENTIALS
3586                 POPT_COMMON_VERSION
3587                 POPT_TABLEEND
3588         };
3589
3590         setup_logging("smbtorture", DEBUG_STDOUT);
3591
3592 #ifdef HAVE_SETBUFFER
3593         setbuffer(stdout, NULL, 0);
3594 #endif
3595
3596         pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options, 
3597                                 POPT_CONTEXT_KEEP_FIRST);
3598
3599         poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
3600
3601         while((opt = poptGetNextOpt(pc)) != -1) {
3602                 switch (opt) {
3603                 case OPT_LOADFILE:
3604                         lp_set_cmdline("torture:loadfile", poptGetOptArg(pc));
3605                         break;
3606                 case OPT_UNCLIST:
3607                         lp_set_cmdline("torture:unclist", poptGetOptArg(pc));
3608                         break;
3609                 case OPT_TIMELIMIT:
3610                         lp_set_cmdline("torture:timelimit", poptGetOptArg(pc));
3611                         break;
3612                 case OPT_DNS:
3613                         parse_dns(poptGetOptArg(pc));
3614                         break;
3615                 case OPT_DANGEROUS:
3616                         lp_set_cmdline("torture:dangerous", "1");
3617                         break;
3618                 default:
3619                         d_printf("Invalid option %s: %s\n", 
3620                                  poptBadOption(pc, 0), poptStrerror(opt));
3621                         usage(pc);
3622                         exit(1);
3623                 }
3624         }
3625
3626         lp_load(dyn_CONFIGFILE,True,False,False);
3627         load_interfaces();
3628         srandom(time(NULL));
3629
3630         argv_new = (const char **)poptGetArgs(pc);
3631
3632         argc_new = argc;
3633         for (i=0; i<argc; i++) {
3634                 if (argv_new[i] == NULL) {
3635                         argc_new = i;
3636                         break;
3637                 }
3638         }
3639
3640         if (argc_new < 3) {
3641                 usage(pc);
3642                 exit(1);
3643         }
3644
3645         for(p = argv_new[1]; *p; p++) {
3646                 if(*p == '\\')
3647                         *p = '/';
3648         }
3649
3650         /* see if its a RPC transport specifier */
3651         if (strncmp(argv_new[1], "ncacn_", 6) == 0) {
3652                 lp_set_cmdline("torture:binding", argv_new[1]);
3653         } else {
3654                 char *binding = NULL;
3655                 char *host = NULL, *share = NULL;
3656
3657                 if (!parse_unc(argv_new[1], &host, &share)) {
3658                         usage(pc);
3659                 }
3660
3661                 lp_set_cmdline("torture:host", host);
3662                 lp_set_cmdline("torture:share", share);
3663                 asprintf(&binding, "ncacn_np:%s", host);
3664                 lp_set_cmdline("torture:binding", binding);
3665         }
3666
3667         if (!lp_parm_string(-1,"torture","username")) {
3668                 lp_set_cmdline("torture:username", cmdline_get_username());
3669         }
3670         if (!lp_parm_string(-1,"torture","userdomain")) {
3671                 /* 
3672                  * backward compatibility
3673                  * maybe we should remove this to make this consistent
3674                  * for all cmdline tools
3675                  * --metze
3676                  */
3677                 if (strequal(lp_netbios_name(),cmdline_get_userdomain())) {
3678                         cmdline_set_userdomain(lp_workgroup());
3679                 }
3680                 lp_set_cmdline("torture:userdomain", cmdline_get_userdomain());
3681         }
3682         if (!lp_parm_string(-1,"torture","password")) {
3683                 lp_set_cmdline("torture:password", cmdline_get_userpassword());
3684         }
3685
3686         if (argc_new == 0) {
3687                 printf("You must specify a test to run, or 'ALL'\n");
3688         } else {
3689                 for (i=2;i<argc_new;i++) {
3690                         if (!run_test(argv_new[i])) {
3691                                 correct = False;
3692                         }
3693                 }
3694         }
3695
3696         if (correct) {
3697                 return(0);
3698         } else {
3699                 return(1);
3700         }
3701 }