r2056: Allow the compiler to check this format string.
[gd/samba-autobuild/.git] / source4 / torture / torture.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-2003
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
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();
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 *password = lp_parm_string(-1, "torture", "password");
91
92         if (use_kerberos)
93                 flags |= SMBCLI_FULL_CONNECTION_USE_KERBEROS;
94
95         status = smbcli_full_connection(c, lp_netbios_name(),
96                                      hostname, NULL, 
97                                      sharename, "?????", 
98                                      username, username[0]?lp_workgroup():"",
99                                      password, flags, &retry);
100         if (!NT_STATUS_IS_OK(status)) {
101                 printf("Failed to open connection - %s\n", nt_errstr(status));
102                 return False;
103         }
104
105         (*c)->transport->options.use_oplocks = use_oplocks;
106         (*c)->transport->options.use_level2_oplocks = use_level_II_oplocks;
107         (*c)->transport->socket->timeout = 120000;
108
109         return True;
110 }
111
112 BOOL torture_open_connection(struct smbcli_state **c)
113 {
114         const char *host = lp_parm_string(-1, "torture", "host");
115         const char *share = lp_parm_string(-1, "torture", "share");
116
117         return torture_open_connection_share(c, host, share);
118 }
119
120
121
122 BOOL torture_close_connection(struct smbcli_state *c)
123 {
124         BOOL ret = True;
125         DEBUG(9,("torture_close_connection: smbcli_state@%p\n", c));
126         if (!c) return True;
127         if (NT_STATUS_IS_ERR(smbcli_tdis(c))) {
128                 printf("tdis failed (%s)\n", smbcli_errstr(c->tree));
129                 ret = False;
130         }
131         DEBUG(9,("torture_close_connection: call smbcli_shutdown\n"));
132         smbcli_shutdown(c);
133         DEBUG(9,("torture_close_connection: exit\n"));
134         return ret;
135 }
136
137
138 /* open a rpc connection to a named pipe */
139 NTSTATUS torture_rpc_connection(struct dcerpc_pipe **p, 
140                                 const char *pipe_name,
141                                 const char *pipe_uuid, 
142                                 uint32_t pipe_version)
143 {
144         NTSTATUS status;
145         const char *binding = lp_parm_string(-1, "torture", "binding");
146
147         if (!binding) {
148                 printf("You must specify a ncacn binding string\n");
149                 return NT_STATUS_INVALID_PARAMETER;
150         }
151
152         status = dcerpc_pipe_connect(p, binding, pipe_uuid, pipe_version,
153                                      lp_workgroup(), 
154                                      lp_parm_string(-1, "torture", "username"),
155                                      lp_parm_string(-1, "torture", "password"));
156  
157         return status;
158 }
159
160 /* close a rpc connection to a named pipe */
161 NTSTATUS torture_rpc_close(struct dcerpc_pipe *p)
162 {
163         dcerpc_pipe_close(p);
164         return NT_STATUS_OK;
165 }
166
167
168 /* check if the server produced the expected error code */
169 static BOOL check_error(int line, struct smbcli_state *c, 
170                         uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
171 {
172         if (smbcli_is_dos_error(c->tree)) {
173                 uint8_t class;
174                 uint32_t num;
175
176                 /* Check DOS error */
177
178                 smbcli_dos_error(c, &class, &num);
179
180                 if (eclass != class || ecode != num) {
181                         printf("unexpected error code class=%d code=%d\n", 
182                                (int)class, (int)num);
183                         printf(" expected %d/%d %s (line=%d)\n", 
184                                (int)eclass, (int)ecode, nt_errstr(nterr), line);
185                         return False;
186                 }
187
188         } else {
189                 NTSTATUS status;
190
191                 /* Check NT error */
192
193                 status = smbcli_nt_error(c->tree);
194
195                 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
196                         printf("unexpected error code %s\n", nt_errstr(status));
197                         printf(" expected %s (line=%d)\n", nt_errstr(nterr), line);
198                         return False;
199                 }
200         }
201
202         return True;
203 }
204
205
206 static BOOL wait_lock(struct smbcli_state *c, int fnum, uint32_t offset, uint32_t len)
207 {
208         while (NT_STATUS_IS_ERR(smbcli_lock(c->tree, fnum, offset, len, -1, WRITE_LOCK))) {
209                 if (!check_error(__LINE__, c, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
210         }
211         return True;
212 }
213
214
215 static BOOL rw_torture(struct smbcli_state *c)
216 {
217         const char *lockfname = "\\torture.lck";
218         char *fname;
219         int fnum;
220         int fnum2;
221         pid_t pid2, pid = getpid();
222         int i, j;
223         char buf[1024];
224         BOOL correct = True;
225
226         fnum2 = smbcli_open(c->tree, lockfname, O_RDWR | O_CREAT | O_EXCL, 
227                          DENY_NONE);
228         if (fnum2 == -1)
229                 fnum2 = smbcli_open(c->tree, lockfname, O_RDWR, DENY_NONE);
230         if (fnum2 == -1) {
231                 printf("open of %s failed (%s)\n", lockfname, smbcli_errstr(c->tree));
232                 return False;
233         }
234
235
236         for (i=0;i<torture_numops;i++) {
237                 uint_t n = (uint_t)sys_random()%10;
238                 if (i % 10 == 0) {
239                         printf("%d\r", i); fflush(stdout);
240                 }
241                 asprintf(&fname, "\\torture.%u", n);
242
243                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
244                         return False;
245                 }
246
247                 fnum = smbcli_open(c->tree, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
248                 if (fnum == -1) {
249                         printf("open failed (%s)\n", smbcli_errstr(c->tree));
250                         correct = False;
251                         break;
252                 }
253
254                 if (smbcli_write(c->tree, fnum, 0, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
255                         printf("write failed (%s)\n", smbcli_errstr(c->tree));
256                         correct = False;
257                 }
258
259                 for (j=0;j<50;j++) {
260                         if (smbcli_write(c->tree, fnum, 0, (char *)buf, 
261                                       sizeof(pid)+(j*sizeof(buf)), 
262                                       sizeof(buf)) != sizeof(buf)) {
263                                 printf("write failed (%s)\n", smbcli_errstr(c->tree));
264                                 correct = False;
265                         }
266                 }
267
268                 pid2 = 0;
269
270                 if (smbcli_read(c->tree, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
271                         printf("read failed (%s)\n", smbcli_errstr(c->tree));
272                         correct = False;
273                 }
274
275                 if (pid2 != pid) {
276                         printf("data corruption!\n");
277                         correct = False;
278                 }
279
280                 if (NT_STATUS_IS_ERR(smbcli_close(c->tree, fnum))) {
281                         printf("close failed (%s)\n", smbcli_errstr(c->tree));
282                         correct = False;
283                 }
284
285                 if (NT_STATUS_IS_ERR(smbcli_unlink(c->tree, fname))) {
286                         printf("unlink failed (%s)\n", smbcli_errstr(c->tree));
287                         correct = False;
288                 }
289
290                 if (NT_STATUS_IS_ERR(smbcli_unlock(c->tree, fnum2, n*sizeof(int), sizeof(int)))) {
291                         printf("unlock failed (%s)\n", smbcli_errstr(c->tree));
292                         correct = False;
293                 }
294                 free(fname);
295         }
296
297         smbcli_close(c->tree, fnum2);
298         smbcli_unlink(c->tree, lockfname);
299
300         printf("%d\n", i);
301
302         return correct;
303 }
304
305 static BOOL run_torture(struct smbcli_state *cli, int dummy)
306 {
307         BOOL ret;
308
309         ret = rw_torture(cli);
310         
311         if (!torture_close_connection(cli)) {
312                 ret = False;
313         }
314
315         return ret;
316 }
317
318 static BOOL rw_torture3(struct smbcli_state *c, const char *lockfname)
319 {
320         int fnum = -1;
321         uint_t i = 0;
322         char buf[131072];
323         char buf_rd[131072];
324         uint_t count;
325         uint_t countprev = 0;
326         ssize_t sent = 0;
327         BOOL correct = True;
328
329         srandom(1);
330         for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
331         {
332                 SIVAL(buf, i, sys_random());
333         }
334
335         if (procnum == 0)
336         {
337                 fnum = smbcli_open(c->tree, lockfname, O_RDWR | O_CREAT | O_EXCL, 
338                                 DENY_NONE);
339                 if (fnum == -1) {
340                         printf("first open read/write of %s failed (%s)\n",
341                                         lockfname, smbcli_errstr(c->tree));
342                         return False;
343                 }
344         }
345         else
346         {
347                 for (i = 0; i < 500 && fnum == -1; i++)
348                 {
349                         fnum = smbcli_open(c->tree, lockfname, O_RDONLY, 
350                                         DENY_NONE);
351                         msleep(10);
352                 }
353                 if (fnum == -1) {
354                         printf("second open read-only of %s failed (%s)\n",
355                                         lockfname, smbcli_errstr(c->tree));
356                         return False;
357                 }
358         }
359
360         i = 0;
361         for (count = 0; count < sizeof(buf); count += sent)
362         {
363                 if (count >= countprev) {
364                         printf("%d %8d\r", i, count);
365                         fflush(stdout);
366                         i++;
367                         countprev += (sizeof(buf) / 20);
368                 }
369
370                 if (procnum == 0)
371                 {
372                         sent = ((uint_t)sys_random()%(20))+ 1;
373                         if (sent > sizeof(buf) - count)
374                         {
375                                 sent = sizeof(buf) - count;
376                         }
377
378                         if (smbcli_write(c->tree, fnum, 0, buf+count, count, (size_t)sent) != sent) {
379                                 printf("write failed (%s)\n", smbcli_errstr(c->tree));
380                                 correct = False;
381                         }
382                 }
383                 else
384                 {
385                         sent = smbcli_read(c->tree, fnum, buf_rd+count, count,
386                                         sizeof(buf)-count);
387                         if (sent < 0)
388                         {
389                                 printf("read failed offset:%d size:%d (%s)\n",
390                                                 count, sizeof(buf)-count,
391                                                 smbcli_errstr(c->tree));
392                                 correct = False;
393                                 sent = 0;
394                         }
395                         if (sent > 0)
396                         {
397                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
398                                 {
399                                         printf("read/write compare failed\n");
400                                         printf("offset: %d req %d recvd %d\n",
401                                                 count, sizeof(buf)-count, sent);
402                                         correct = False;
403                                         break;
404                                 }
405                         }
406                 }
407
408         }
409
410         if (NT_STATUS_IS_ERR(smbcli_close(c->tree, fnum))) {
411                 printf("close failed (%s)\n", smbcli_errstr(c->tree));
412                 correct = False;
413         }
414
415         return correct;
416 }
417
418 static BOOL rw_torture2(struct smbcli_state *c1, struct smbcli_state *c2)
419 {
420         const char *lockfname = "\\torture2.lck";
421         int fnum1;
422         int fnum2;
423         int i;
424         uint8_t buf[131072];
425         uint8_t buf_rd[131072];
426         BOOL correct = True;
427         ssize_t bytes_read, bytes_written;
428
429         if (smbcli_deltree(c1->tree, lockfname) == -1) {
430                 printf("unlink failed (%s)\n", smbcli_errstr(c1->tree));
431         }
432
433         fnum1 = smbcli_open(c1->tree, lockfname, O_RDWR | O_CREAT | O_EXCL, 
434                          DENY_NONE);
435         if (fnum1 == -1) {
436                 printf("first open read/write of %s failed (%s)\n",
437                                 lockfname, smbcli_errstr(c1->tree));
438                 return False;
439         }
440         fnum2 = smbcli_open(c2->tree, lockfname, O_RDONLY, 
441                          DENY_NONE);
442         if (fnum2 == -1) {
443                 printf("second open read-only of %s failed (%s)\n",
444                                 lockfname, smbcli_errstr(c2->tree));
445                 smbcli_close(c1->tree, fnum1);
446                 return False;
447         }
448
449         printf("Checking data integrity over %d ops\n", torture_numops);
450
451         for (i=0;i<torture_numops;i++)
452         {
453                 size_t buf_size = ((uint_t)sys_random()%(sizeof(buf)-1))+ 1;
454                 if (i % 10 == 0) {
455                         printf("%d\r", i); fflush(stdout);
456                 }
457
458                 generate_random_buffer(buf, buf_size);
459
460                 if ((bytes_written = smbcli_write(c1->tree, fnum1, 0, buf, 0, buf_size)) != buf_size) {
461                         printf("write failed (%s)\n", smbcli_errstr(c1->tree));
462                         printf("wrote %d, expected %d\n", bytes_written, buf_size); 
463                         correct = False;
464                         break;
465                 }
466
467                 if ((bytes_read = smbcli_read(c2->tree, fnum2, buf_rd, 0, buf_size)) != buf_size) {
468                         printf("read failed (%s)\n", smbcli_errstr(c2->tree));
469                         printf("read %d, expected %d\n", bytes_read, buf_size); 
470                         correct = False;
471                         break;
472                 }
473
474                 if (memcmp(buf_rd, buf, buf_size) != 0)
475                 {
476                         printf("read/write compare failed\n");
477                         correct = False;
478                         break;
479                 }
480         }
481
482         if (NT_STATUS_IS_ERR(smbcli_close(c2->tree, fnum2))) {
483                 printf("close failed (%s)\n", smbcli_errstr(c2->tree));
484                 correct = False;
485         }
486         if (NT_STATUS_IS_ERR(smbcli_close(c1->tree, fnum1))) {
487                 printf("close failed (%s)\n", smbcli_errstr(c1->tree));
488                 correct = False;
489         }
490
491         if (NT_STATUS_IS_ERR(smbcli_unlink(c1->tree, lockfname))) {
492                 printf("unlink failed (%s)\n", smbcli_errstr(c1->tree));
493                 correct = False;
494         }
495
496         return correct;
497 }
498
499 static BOOL run_readwritetest(int dummy)
500 {
501         struct smbcli_state *cli1, *cli2;
502         BOOL test1, test2 = True;
503
504         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
505                 return False;
506         }
507
508         printf("starting readwritetest\n");
509
510         test1 = rw_torture2(cli1, cli2);
511         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
512
513         if (test1) {
514                 test2 = rw_torture2(cli1, cli1);
515                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
516         }
517
518         if (!torture_close_connection(cli1)) {
519                 test1 = False;
520         }
521
522         if (!torture_close_connection(cli2)) {
523                 test2 = False;
524         }
525
526         return (test1 && test2);
527 }
528
529 static BOOL run_readwritemulti(struct smbcli_state *cli, int dummy)
530 {
531         BOOL test;
532
533         test = rw_torture3(cli, "\\multitest.txt");
534
535         if (!torture_close_connection(cli)) {
536                 test = False;
537         }
538         
539         return test;
540 }
541
542
543 /*
544   This test checks for two things:
545
546   1) correct support for retaining locks over a close (ie. the server
547      must not use posix semantics)
548   2) support for lock timeouts
549  */
550 static BOOL run_locktest1(int dummy)
551 {
552         struct smbcli_state *cli1, *cli2;
553         const char *fname = "\\lockt1.lck";
554         int fnum1, fnum2, fnum3;
555         time_t t1, t2;
556         uint_t lock_timeout;
557
558         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
559                 return False;
560         }
561
562         printf("starting locktest1\n");
563
564         smbcli_unlink(cli1->tree, fname);
565
566         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
567         if (fnum1 == -1) {
568                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
569                 return False;
570         }
571         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
572         if (fnum2 == -1) {
573                 printf("open2 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
574                 return False;
575         }
576         fnum3 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
577         if (fnum3 == -1) {
578                 printf("open3 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
579                 return False;
580         }
581
582         if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
583                 printf("lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
584                 return False;
585         }
586
587
588         if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
589                 printf("lock2 succeeded! This is a locking bug\n");
590                 return False;
591         } else {
592                 if (!check_error(__LINE__, cli2, ERRDOS, ERRlock, 
593                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
594         }
595
596
597         lock_timeout = (6 + (random() % 20));
598         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
599         t1 = time(NULL);
600         if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK))) {
601                 printf("lock3 succeeded! This is a locking bug\n");
602                 return False;
603         } else {
604                 if (!check_error(__LINE__, cli2, ERRDOS, ERRlock, 
605                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
606         }
607         t2 = time(NULL);
608
609         if (t2 - t1 < 5) {
610                 printf("error: This server appears not to support timed lock requests\n");
611         }
612         printf("server slept for %u seconds for a %u second timeout\n",
613                (uint_t)(t2-t1), lock_timeout);
614
615         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
616                 printf("close1 failed (%s)\n", smbcli_errstr(cli1->tree));
617                 return False;
618         }
619
620         if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
621                 printf("lock4 succeeded! This is a locking bug\n");
622                 return False;
623         } else {
624                 if (!check_error(__LINE__, cli2, ERRDOS, ERRlock, 
625                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
626         }
627
628         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
629                 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
630                 return False;
631         }
632
633         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum3))) {
634                 printf("close3 failed (%s)\n", smbcli_errstr(cli2->tree));
635                 return False;
636         }
637
638         if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, fname))) {
639                 printf("unlink failed (%s)\n", smbcli_errstr(cli1->tree));
640                 return False;
641         }
642
643
644         if (!torture_close_connection(cli1)) {
645                 return False;
646         }
647
648         if (!torture_close_connection(cli2)) {
649                 return False;
650         }
651
652         printf("Passed locktest1\n");
653         return True;
654 }
655
656 /*
657   this checks to see if a secondary tconx can use open files from an
658   earlier tconx
659  */
660 static BOOL run_tcon_test(int dummy)
661 {
662         struct smbcli_state *cli;
663         const char *fname = "\\tcontest.tmp";
664         int fnum1;
665         uint16_t cnum1, cnum2, cnum3;
666         uint16_t vuid1, vuid2;
667         char buf[4];
668         BOOL ret = True;
669         struct smbcli_tree *tree1;
670         const char *host = lp_parm_string(-1, "torture", "host");
671         const char *share = lp_parm_string(-1, "torture", "share");
672         const char *password = lp_parm_string(-1, "torture", "password");
673
674         if (!torture_open_connection(&cli)) {
675                 return False;
676         }
677
678         printf("starting tcontest\n");
679
680         if (smbcli_deltree(cli->tree, fname) == -1) {
681                 printf("unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
682         }
683
684         fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
685         if (fnum1 == -1) {
686                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
687                 return False;
688         }
689
690         cnum1 = cli->tree->tid;
691         vuid1 = cli->session->vuid;
692
693         memset(&buf, 0, 4); /* init buf so valgrind won't complain */
694         if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) != 4) {
695                 printf("initial write failed (%s)\n", smbcli_errstr(cli->tree));
696                 return False;
697         }
698
699         tree1 = cli->tree;      /* save old tree connection */
700         if (NT_STATUS_IS_ERR(smbcli_send_tconX(cli, share, "?????", password))) {
701                 printf("%s refused 2nd tree connect (%s)\n", host,
702                            smbcli_errstr(cli->tree));
703                 smbcli_shutdown(cli);
704                 return False;
705         }
706
707         cnum2 = cli->tree->tid;
708         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
709         vuid2 = cli->session->vuid + 1;
710
711         /* try a write with the wrong tid */
712         cli->tree->tid = cnum2;
713
714         if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
715                 printf("* server allows write with wrong TID\n");
716                 ret = False;
717         } else {
718                 printf("server fails write with wrong TID : %s\n", smbcli_errstr(cli->tree));
719         }
720
721
722         /* try a write with an invalid tid */
723         cli->tree->tid = cnum3;
724
725         if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
726                 printf("* server allows write with invalid TID\n");
727                 ret = False;
728         } else {
729                 printf("server fails write with invalid TID : %s\n", smbcli_errstr(cli->tree));
730         }
731
732         /* try a write with an invalid vuid */
733         cli->session->vuid = vuid2;
734         cli->tree->tid = cnum1;
735
736         if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
737                 printf("* server allows write with invalid VUID\n");
738                 ret = False;
739         } else {
740                 printf("server fails write with invalid VUID : %s\n", smbcli_errstr(cli->tree));
741         }
742
743         cli->session->vuid = vuid1;
744         cli->tree->tid = cnum1;
745
746         if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum1))) {
747                 printf("close failed (%s)\n", smbcli_errstr(cli->tree));
748                 return False;
749         }
750
751         cli->tree->tid = cnum2;
752
753         if (NT_STATUS_IS_ERR(smbcli_tdis(cli))) {
754                 printf("secondary tdis failed (%s)\n", smbcli_errstr(cli->tree));
755                 return False;
756         }
757
758         cli->tree = tree1;  /* restore initial tree */
759         cli->tree->tid = cnum1;
760
761         if (!torture_close_connection(cli)) {
762                 return False;
763         }
764
765         return ret;
766 }
767
768
769
770 static BOOL tcon_devtest(struct smbcli_state *cli,
771                          const char *myshare, const char *devtype,
772                          NTSTATUS expected_error)
773 {
774         BOOL status;
775         BOOL ret;
776         const char *password = lp_parm_string(-1, "torture", "password");
777
778         status = NT_STATUS_IS_OK(smbcli_send_tconX(cli, myshare, devtype, 
779                                                 password));
780
781         printf("Trying share %s with devtype %s\n", myshare, devtype);
782
783         if (NT_STATUS_IS_OK(expected_error)) {
784                 if (status) {
785                         ret = True;
786                 } else {
787                         printf("tconX to share %s with type %s "
788                                "should have succeeded but failed\n",
789                                myshare, devtype);
790                         ret = False;
791                 }
792                 smbcli_tdis(cli);
793         } else {
794                 if (status) {
795                         printf("tconx to share %s with type %s "
796                                "should have failed but succeeded\n",
797                                myshare, devtype);
798                         ret = False;
799                 } else {
800                         if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),
801                                             expected_error)) {
802                                 ret = True;
803                         } else {
804                                 printf("Returned unexpected error\n");
805                                 ret = False;
806                         }
807                 }
808         }
809         return ret;
810 }
811
812 /*
813  checks for correct tconX support
814  */
815 static BOOL run_tcon_devtype_test(int dummy)
816 {
817         struct smbcli_state *cli1 = NULL;
818         BOOL retry;
819         int flags = 0;
820         NTSTATUS status;
821         BOOL ret = True;
822         const char *host = lp_parm_string(-1, "torture", "host");
823         const char *share = lp_parm_string(-1, "torture", "share");
824         const char *username = lp_parm_string(-1, "torture", "username");
825         const char *password = lp_parm_string(-1, "torture", "password");
826         
827         status = smbcli_full_connection(&cli1, lp_netbios_name(),
828                                      host, NULL, 
829                                      share, "?????",
830                                      username, lp_workgroup(),
831                                      password, flags, &retry);
832
833         if (!NT_STATUS_IS_OK(status)) {
834                 printf("could not open connection\n");
835                 return False;
836         }
837
838         if (!tcon_devtest(cli1, "IPC$", "A:", NT_STATUS_BAD_DEVICE_TYPE))
839                 ret = False;
840
841         if (!tcon_devtest(cli1, "IPC$", "?????", NT_STATUS_OK))
842                 ret = False;
843
844         if (!tcon_devtest(cli1, "IPC$", "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
845                 ret = False;
846
847         if (!tcon_devtest(cli1, "IPC$", "IPC", NT_STATUS_OK))
848                 ret = False;
849                         
850         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
851                 ret = False;
852
853         if (!tcon_devtest(cli1, share, "A:", NT_STATUS_OK))
854                 ret = False;
855
856         if (!tcon_devtest(cli1, share, "?????", NT_STATUS_OK))
857                 ret = False;
858
859         if (!tcon_devtest(cli1, share, "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
860                 ret = False;
861
862         if (!tcon_devtest(cli1, share, "IPC", NT_STATUS_BAD_DEVICE_TYPE))
863                 ret = False;
864                         
865         if (!tcon_devtest(cli1, share, "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
866                 ret = False;
867
868         smbcli_shutdown(cli1);
869
870         if (ret)
871                 printf("Passed tcondevtest\n");
872
873         return ret;
874 }
875
876
877 /*
878   This test checks that 
879
880   1) the server supports multiple locking contexts on the one SMB
881   connection, distinguished by PID.  
882
883   2) the server correctly fails overlapping locks made by the same PID (this
884      goes against POSIX behaviour, which is why it is tricky to implement)
885
886   3) the server denies unlock requests by an incorrect client PID
887 */
888 static BOOL run_locktest2(int dummy)
889 {
890         struct smbcli_state *cli;
891         const char *fname = "\\lockt2.lck";
892         int fnum1, fnum2, fnum3;
893         BOOL correct = True;
894
895         if (!torture_open_connection(&cli)) {
896                 return False;
897         }
898
899         printf("starting locktest2\n");
900
901         smbcli_unlink(cli->tree, fname);
902
903         printf("Testing pid context\n");
904         
905         cli->session->pid = 1;
906
907         fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
908         if (fnum1 == -1) {
909                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
910                 return False;
911         }
912
913         fnum2 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
914         if (fnum2 == -1) {
915                 printf("open2 of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
916                 return False;
917         }
918
919         cli->session->pid = 2;
920
921         fnum3 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
922         if (fnum3 == -1) {
923                 printf("open3 of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
924                 return False;
925         }
926
927         cli->session->pid = 1;
928
929         if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
930                 printf("lock1 failed (%s)\n", smbcli_errstr(cli->tree));
931                 return False;
932         }
933
934         if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
935                 printf("WRITE lock1 succeeded! This is a locking bug\n");
936                 correct = False;
937         } else {
938                 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, 
939                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
940         }
941
942         if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum2, 0, 4, 0, WRITE_LOCK))) {
943                 printf("WRITE lock2 succeeded! This is a locking bug\n");
944                 correct = False;
945         } else {
946                 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, 
947                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
948         }
949
950         if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum2, 0, 4, 0, READ_LOCK))) {
951                 printf("READ lock2 succeeded! This is a locking bug\n");
952                 correct = False;
953         } else {
954                 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, 
955                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
956         }
957
958         if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum1, 100, 4, 0, WRITE_LOCK))) {
959                 printf("lock at 100 failed (%s)\n", smbcli_errstr(cli->tree));
960         }
961
962         cli->session->pid = 2;
963
964         if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 100, 4))) {
965                 printf("unlock at 100 succeeded! This is a locking bug\n");
966                 correct = False;
967         }
968
969         if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 0, 4))) {
970                 printf("unlock1 succeeded! This is a locking bug\n");
971                 correct = False;
972         } else {
973                 if (!check_error(__LINE__, cli, 
974                                  ERRDOS, ERRlock, 
975                                  NT_STATUS_RANGE_NOT_LOCKED)) return False;
976         }
977
978         if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 0, 8))) {
979                 printf("unlock2 succeeded! This is a locking bug\n");
980                 correct = False;
981         } else {
982                 if (!check_error(__LINE__, cli, 
983                                  ERRDOS, ERRlock, 
984                                  NT_STATUS_RANGE_NOT_LOCKED)) return False;
985         }
986
987         if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
988                 printf("lock3 succeeded! This is a locking bug\n");
989                 correct = False;
990         } else {
991                 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
992         }
993
994         cli->session->pid = 1;
995
996         if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum1))) {
997                 printf("close1 failed (%s)\n", smbcli_errstr(cli->tree));
998                 return False;
999         }
1000
1001         if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum2))) {
1002                 printf("close2 failed (%s)\n", smbcli_errstr(cli->tree));
1003                 return False;
1004         }
1005
1006         if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum3))) {
1007                 printf("close3 failed (%s)\n", smbcli_errstr(cli->tree));
1008                 return False;
1009         }
1010
1011         if (!torture_close_connection(cli)) {
1012                 correct = False;
1013         }
1014
1015         printf("locktest2 finished\n");
1016
1017         return correct;
1018 }
1019
1020
1021 /*
1022   This test checks that 
1023
1024   1) the server supports the full offset range in lock requests
1025 */
1026 static BOOL run_locktest3(int dummy)
1027 {
1028         struct smbcli_state *cli1, *cli2;
1029         const char *fname = "\\lockt3.lck";
1030         int fnum1, fnum2, i;
1031         uint32_t offset;
1032         BOOL correct = True;
1033
1034 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1035
1036         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
1037                 return False;
1038         }
1039
1040         printf("starting locktest3\n");
1041
1042         printf("Testing 32 bit offset ranges\n");
1043
1044         smbcli_unlink(cli1->tree, fname);
1045
1046         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1047         if (fnum1 == -1) {
1048                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1049                 return False;
1050         }
1051         fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
1052         if (fnum2 == -1) {
1053                 printf("open2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1054                 return False;
1055         }
1056
1057         printf("Establishing %d locks\n", torture_numops);
1058
1059         for (offset=i=0;i<torture_numops;i++) {
1060                 NEXT_OFFSET;
1061                 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK))) {
1062                         printf("lock1 %d failed (%s)\n", 
1063                                i,
1064                                smbcli_errstr(cli1->tree));
1065                         return False;
1066                 }
1067
1068                 if (NT_STATUS_IS_ERR(smbcli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK))) {
1069                         printf("lock2 %d failed (%s)\n", 
1070                                i,
1071                                smbcli_errstr(cli1->tree));
1072                         return False;
1073                 }
1074         }
1075
1076         printf("Testing %d locks\n", torture_numops);
1077
1078         for (offset=i=0;i<torture_numops;i++) {
1079                 NEXT_OFFSET;
1080
1081                 if (NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, offset-2, 1, 0, WRITE_LOCK))) {
1082                         printf("error: lock1 %d succeeded!\n", i);
1083                         return False;
1084                 }
1085
1086                 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, offset-1, 1, 0, WRITE_LOCK))) {
1087                         printf("error: lock2 %d succeeded!\n", i);
1088                         return False;
1089                 }
1090
1091                 if (NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK))) {
1092                         printf("error: lock3 %d succeeded!\n", i);
1093                         return False;
1094                 }
1095
1096                 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK))) {
1097                         printf("error: lock4 %d succeeded!\n", i);
1098                         return False;
1099                 }
1100         }
1101
1102         printf("Removing %d locks\n", torture_numops);
1103
1104         for (offset=i=0;i<torture_numops;i++) {
1105                 NEXT_OFFSET;
1106
1107                 if (NT_STATUS_IS_ERR(smbcli_unlock(cli1->tree, fnum1, offset-1, 1))) {
1108                         printf("unlock1 %d failed (%s)\n", 
1109                                i,
1110                                smbcli_errstr(cli1->tree));
1111                         return False;
1112                 }
1113
1114                 if (NT_STATUS_IS_ERR(smbcli_unlock(cli2->tree, fnum2, offset-2, 1))) {
1115                         printf("unlock2 %d failed (%s)\n", 
1116                                i,
1117                                smbcli_errstr(cli1->tree));
1118                         return False;
1119                 }
1120         }
1121
1122         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1123                 printf("close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1124                 return False;
1125         }
1126
1127         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1128                 printf("close2 failed (%s)\n", smbcli_errstr(cli2->tree));
1129                 return False;
1130         }
1131
1132         if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, fname))) {
1133                 printf("unlink failed (%s)\n", smbcli_errstr(cli1->tree));
1134                 return False;
1135         }
1136
1137         if (!torture_close_connection(cli1)) {
1138                 correct = False;
1139         }
1140         
1141         if (!torture_close_connection(cli2)) {
1142                 correct = False;
1143         }
1144
1145         printf("finished locktest3\n");
1146
1147         return correct;
1148 }
1149
1150 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1151         printf("** "); correct = False; \
1152         }
1153
1154 /*
1155   looks at overlapping locks
1156 */
1157 static BOOL run_locktest4(int dummy)
1158 {
1159         struct smbcli_state *cli1, *cli2;
1160         const char *fname = "\\lockt4.lck";
1161         int fnum1, fnum2, f;
1162         BOOL ret;
1163         char buf[1000];
1164         BOOL correct = True;
1165
1166         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
1167                 return False;
1168         }
1169
1170         printf("starting locktest4\n");
1171
1172         smbcli_unlink(cli1->tree, fname);
1173
1174         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1175         fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
1176
1177         memset(buf, 0, sizeof(buf));
1178
1179         if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1180                 printf("Failed to create file\n");
1181                 correct = False;
1182                 goto fail;
1183         }
1184
1185         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1186               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 2, 4, 0, WRITE_LOCK));
1187         EXPECTED(ret, False);
1188         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1189             
1190         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 10, 4, 0, READ_LOCK)) &&
1191               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 12, 4, 0, READ_LOCK));
1192         EXPECTED(ret, True);
1193         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1194
1195         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1196               NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 22, 4, 0, WRITE_LOCK));
1197         EXPECTED(ret, False);
1198         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1199             
1200         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 30, 4, 0, READ_LOCK)) &&
1201                 NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 32, 4, 0, READ_LOCK));
1202         EXPECTED(ret, True);
1203         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1204         
1205         ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1206               NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 42, 4, 0, WRITE_LOCK)));
1207         EXPECTED(ret, False);
1208         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1209             
1210         ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 50, 4, 0, READ_LOCK))) &&
1211               NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 52, 4, 0, READ_LOCK)));
1212         EXPECTED(ret, True);
1213         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1214
1215         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK)) &&
1216               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK));
1217         EXPECTED(ret, True);
1218         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1219
1220         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1221               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK));
1222         EXPECTED(ret, False);
1223         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1224
1225         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 80, 4, 0, READ_LOCK)) &&
1226               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 80, 4, 0, WRITE_LOCK));
1227         EXPECTED(ret, False);
1228         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1229
1230         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 90, 4, 0, WRITE_LOCK)) &&
1231               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 90, 4, 0, READ_LOCK));
1232         EXPECTED(ret, True);
1233         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1234
1235         ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 100, 4, 0, WRITE_LOCK))) &&
1236               NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 100, 4, 0, READ_LOCK)));
1237         EXPECTED(ret, False);
1238         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1239
1240         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 110, 4, 0, READ_LOCK)) &&
1241               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 112, 4, 0, READ_LOCK)) &&
1242               NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 110, 6));
1243         EXPECTED(ret, False);
1244         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
1245
1246
1247         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 120, 4, 0, WRITE_LOCK)) &&
1248               (smbcli_read(cli2->tree, fnum2, buf, 120, 4) == 4);
1249         EXPECTED(ret, False);
1250         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
1251
1252         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK)) &&
1253               (smbcli_write(cli2->tree, fnum2, 0, buf, 130, 4) == 4);
1254         EXPECTED(ret, False);
1255         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
1256
1257
1258         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) &&
1259               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) &&
1260               NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 140, 4)) &&
1261               NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 140, 4));
1262         EXPECTED(ret, True);
1263         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
1264
1265
1266         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 150, 4, 0, WRITE_LOCK)) &&
1267               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 150, 4, 0, READ_LOCK)) &&
1268               NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 150, 4)) &&
1269               (smbcli_read(cli2->tree, fnum2, buf, 150, 4) == 4) &&
1270               !(smbcli_write(cli2->tree, fnum2, 0, buf, 150, 4) == 4) &&
1271               NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 150, 4));
1272         EXPECTED(ret, True);
1273         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
1274
1275         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 160, 4, 0, READ_LOCK)) &&
1276               NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 160, 4)) &&
1277               (smbcli_write(cli2->tree, fnum2, 0, buf, 160, 4) == 4) &&         
1278               (smbcli_read(cli2->tree, fnum2, buf, 160, 4) == 4);               
1279         EXPECTED(ret, True);
1280         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
1281
1282         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 170, 4, 0, WRITE_LOCK)) &&
1283               NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 170, 4)) &&
1284               (smbcli_write(cli2->tree, fnum2, 0, buf, 170, 4) == 4) &&         
1285               (smbcli_read(cli2->tree, fnum2, buf, 170, 4) == 4);               
1286         EXPECTED(ret, True);
1287         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
1288
1289         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 190, 4, 0, WRITE_LOCK)) &&
1290               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 190, 4, 0, READ_LOCK)) &&
1291               NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 190, 4)) &&
1292               !(smbcli_write(cli2->tree, fnum2, 0, buf, 190, 4) == 4) &&                
1293               (smbcli_read(cli2->tree, fnum2, buf, 190, 4) == 4);               
1294         EXPECTED(ret, True);
1295         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
1296
1297         smbcli_close(cli1->tree, fnum1);
1298         smbcli_close(cli2->tree, fnum2);
1299         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1300         f = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1301         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) &&
1302               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, f, 0, 1, 0, READ_LOCK)) &&
1303               NT_STATUS_IS_OK(smbcli_close(cli1->tree, fnum1)) &&
1304               ((fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE)) != -1) &&
1305               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK));
1306         smbcli_close(cli1->tree, f);
1307         smbcli_close(cli1->tree, fnum1);
1308         EXPECTED(ret, True);
1309         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
1310
1311  fail:
1312         smbcli_close(cli1->tree, fnum1);
1313         smbcli_close(cli2->tree, fnum2);
1314         smbcli_unlink(cli1->tree, fname);
1315         torture_close_connection(cli1);
1316         torture_close_connection(cli2);
1317
1318         printf("finished locktest4\n");
1319         return correct;
1320 }
1321
1322 /*
1323   looks at lock upgrade/downgrade.
1324 */
1325 static BOOL run_locktest5(int dummy)
1326 {
1327         struct smbcli_state *cli1, *cli2;
1328         const char *fname = "\\lockt5.lck";
1329         int fnum1, fnum2, fnum3;
1330         BOOL ret;
1331         char buf[1000];
1332         BOOL correct = True;
1333
1334         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
1335                 return False;
1336         }
1337
1338         printf("starting locktest5\n");
1339
1340         smbcli_unlink(cli1->tree, fname);
1341
1342         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1343         fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
1344         fnum3 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1345
1346         memset(buf, 0, sizeof(buf));
1347
1348         if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1349                 printf("Failed to create file\n");
1350                 correct = False;
1351                 goto fail;
1352         }
1353
1354         /* Check for NT bug... */
1355         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) &&
1356                   NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum3, 0, 1, 0, READ_LOCK));
1357         smbcli_close(cli1->tree, fnum1);
1358         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1359         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK));
1360         EXPECTED(ret, True);
1361         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
1362         smbcli_close(cli1->tree, fnum1);
1363         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1364         smbcli_unlock(cli1->tree, fnum3, 0, 1);
1365
1366         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1367               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 1, 1, 0, READ_LOCK));
1368         EXPECTED(ret, True);
1369         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
1370
1371         ret = NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK));
1372         EXPECTED(ret, False);
1373
1374         printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
1375
1376         /* Unlock the process 2 lock. */
1377         smbcli_unlock(cli2->tree, fnum2, 0, 4);
1378
1379         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum3, 0, 4, 0, READ_LOCK));
1380         EXPECTED(ret, False);
1381
1382         printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
1383
1384         /* Unlock the process 1 fnum3 lock. */
1385         smbcli_unlock(cli1->tree, fnum3, 0, 4);
1386
1387         /* Stack 2 more locks here. */
1388         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK)) &&
1389                   NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK));
1390
1391         EXPECTED(ret, True);
1392         printf("the same process %s stack read locks\n", ret?"can":"cannot");
1393
1394         /* Unlock the first process lock, then check this was the WRITE lock that was
1395                 removed. */
1396
1397 ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4)) &&
1398         NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK));
1399
1400         EXPECTED(ret, True);
1401         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
1402
1403         /* Unlock the process 2 lock. */
1404         smbcli_unlock(cli2->tree, fnum2, 0, 4);
1405
1406         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
1407
1408         ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 1, 1)) &&
1409                   NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4)) &&
1410                   NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4));
1411
1412         EXPECTED(ret, True);
1413         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
1414
1415         /* Ensure the next unlock fails. */
1416         ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4));
1417         EXPECTED(ret, False);
1418         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
1419
1420         /* Ensure connection 2 can get a write lock. */
1421         ret = NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, WRITE_LOCK));
1422         EXPECTED(ret, True);
1423
1424         printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
1425
1426
1427  fail:
1428         smbcli_close(cli1->tree, fnum1);
1429         smbcli_close(cli2->tree, fnum2);
1430         smbcli_unlink(cli1->tree, fname);
1431         if (!torture_close_connection(cli1)) {
1432                 correct = False;
1433         }
1434         if (!torture_close_connection(cli2)) {
1435                 correct = False;
1436         }
1437
1438         printf("finished locktest5\n");
1439        
1440         return correct;
1441 }
1442
1443 /*
1444   tries the unusual lockingX locktype bits
1445 */
1446 static BOOL run_locktest6(int dummy)
1447 {
1448         struct smbcli_state *cli;
1449         const char *fname[1] = { "\\lock6.txt" };
1450         int i;
1451         int fnum;
1452         NTSTATUS status;
1453
1454         if (!torture_open_connection(&cli)) {
1455                 return False;
1456         }
1457
1458         printf("starting locktest6\n");
1459
1460         for (i=0;i<1;i++) {
1461                 printf("Testing %s\n", fname[i]);
1462
1463                 smbcli_unlink(cli->tree, fname[i]);
1464
1465                 fnum = smbcli_open(cli->tree, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1466                 status = smbcli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
1467                 smbcli_close(cli->tree, fnum);
1468                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
1469
1470                 fnum = smbcli_open(cli->tree, fname[i], O_RDWR, DENY_NONE);
1471                 status = smbcli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
1472                 smbcli_close(cli->tree, fnum);
1473                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
1474
1475                 smbcli_unlink(cli->tree, fname[i]);
1476         }
1477
1478         torture_close_connection(cli);
1479
1480         printf("finished locktest6\n");
1481         return True;
1482 }
1483
1484 static BOOL run_locktest7(int dummy)
1485 {
1486         struct smbcli_state *cli1;
1487         const char *fname = "\\lockt7.lck";
1488         int fnum1;
1489         int fnum2;
1490         size_t size;
1491         char buf[200];
1492         BOOL correct = False;
1493
1494         if (!torture_open_connection(&cli1)) {
1495                 return False;
1496         }
1497
1498         printf("starting locktest7\n");
1499
1500         smbcli_unlink(cli1->tree, fname);
1501
1502         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1503
1504         memset(buf, 0, sizeof(buf));
1505
1506         if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1507                 printf("Failed to create file\n");
1508                 goto fail;
1509         }
1510
1511         cli1->session->pid = 1;
1512
1513         if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK))) {
1514                 printf("Unable to apply read lock on range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
1515                 goto fail;
1516         } else {
1517                 printf("pid1 successfully locked range 130:4 for READ\n");
1518         }
1519
1520         if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
1521                 printf("pid1 unable to read the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
1522                 goto fail;
1523         } else {
1524                 printf("pid1 successfully read the range 130:4\n");
1525         }
1526
1527         if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
1528                 printf("pid1 unable to write to the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
1529                 if (NT_STATUS_V(smbcli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
1530                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
1531                         goto fail;
1532                 }
1533         } else {
1534                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
1535                 goto fail;
1536         }
1537
1538         cli1->session->pid = 2;
1539
1540         if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
1541                 printf("pid2 unable to read the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
1542         } else {
1543                 printf("pid2 successfully read the range 130:4\n");
1544         }
1545
1546         if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
1547                 printf("pid2 unable to write to the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
1548                 if (NT_STATUS_V(smbcli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
1549                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
1550                         goto fail;
1551                 }
1552         } else {
1553                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
1554                 goto fail;
1555         }
1556
1557         cli1->session->pid = 1;
1558         smbcli_unlock(cli1->tree, fnum1, 130, 4);
1559
1560         if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, WRITE_LOCK))) {
1561                 printf("Unable to apply write lock on range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
1562                 goto fail;
1563         } else {
1564                 printf("pid1 successfully locked range 130:4 for WRITE\n");
1565         }
1566
1567         if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
1568                 printf("pid1 unable to read the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
1569                 goto fail;
1570         } else {
1571                 printf("pid1 successfully read the range 130:4\n");
1572         }
1573
1574         if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
1575                 printf("pid1 unable to write to the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
1576                 goto fail;
1577         } else {
1578                 printf("pid1 successfully wrote to the range 130:4\n");
1579         }
1580
1581         cli1->session->pid = 2;
1582
1583         if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
1584                 printf("pid2 unable to read the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
1585                 if (NT_STATUS_V(smbcli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
1586                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
1587                         goto fail;
1588                 }
1589         } else {
1590                 printf("pid2 successfully read the range 130:4 (should be denied)\n");
1591                 goto fail;
1592         }
1593
1594         if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
1595                 printf("pid2 unable to write to the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
1596                 if (NT_STATUS_V(smbcli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
1597                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
1598                         goto fail;
1599                 }
1600         } else {
1601                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
1602                 goto fail;
1603         }
1604
1605         printf("Testing truncate of locked file.\n");
1606
1607         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
1608
1609         if (fnum2 == -1) {
1610                 printf("Unable to truncate locked file.\n");
1611                 correct = False;
1612                 goto fail;
1613         } else {
1614                 printf("Truncated locked file.\n");
1615         }
1616
1617         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &size, NULL))) {
1618                 printf("getatr failed (%s)\n", smbcli_errstr(cli1->tree));
1619                 correct = False;
1620                 goto fail;
1621         }
1622
1623         if (size != 0) {
1624                 printf("Unable to truncate locked file. Size was %u\n", size);
1625                 correct = False;
1626                 goto fail;
1627         }
1628
1629         cli1->session->pid = 1;
1630
1631         smbcli_unlock(cli1->tree, fnum1, 130, 4);
1632         correct = True;
1633
1634 fail:
1635         smbcli_close(cli1->tree, fnum1);
1636         smbcli_close(cli1->tree, fnum2);
1637         smbcli_unlink(cli1->tree, fname);
1638         torture_close_connection(cli1);
1639
1640         printf("finished locktest7\n");
1641         return correct;
1642 }
1643
1644 /*
1645 test whether fnums and tids open on one VC are available on another (a major
1646 security hole)
1647 */
1648 static BOOL run_fdpasstest(int dummy)
1649 {
1650         struct smbcli_state *cli1, *cli2;
1651         const char *fname = "\\fdpass.tst";
1652         int fnum1, oldtid;
1653         pstring buf;
1654
1655         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
1656                 return False;
1657         }
1658
1659         printf("starting fdpasstest\n");
1660
1661         smbcli_unlink(cli1->tree, fname);
1662
1663         printf("Opening a file on connection 1\n");
1664
1665         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1666         if (fnum1 == -1) {
1667                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1668                 return False;
1669         }
1670
1671         printf("writing to file on connection 1\n");
1672
1673         if (smbcli_write(cli1->tree, fnum1, 0, "hello world\n", 0, 13) != 13) {
1674                 printf("write failed (%s)\n", smbcli_errstr(cli1->tree));
1675                 return False;
1676         }
1677
1678         oldtid = cli2->tree->tid;
1679         cli2->session->vuid = cli1->session->vuid;
1680         cli2->tree->tid = cli1->tree->tid;
1681         cli2->session->pid = cli1->session->pid;
1682
1683         printf("reading from file on connection 2\n");
1684
1685         if (smbcli_read(cli2->tree, fnum1, buf, 0, 13) == 13) {
1686                 printf("read succeeded! nasty security hole [%s]\n",
1687                        buf);
1688                 return False;
1689         }
1690
1691         smbcli_close(cli1->tree, fnum1);
1692         smbcli_unlink(cli1->tree, fname);
1693
1694         cli2->tree->tid = oldtid;
1695
1696         torture_close_connection(cli1);
1697         torture_close_connection(cli2);
1698
1699         printf("finished fdpasstest\n");
1700         return True;
1701 }
1702
1703
1704 /*
1705   This test checks that 
1706
1707   1) the server does not allow an unlink on a file that is open
1708 */
1709 static BOOL run_unlinktest(int dummy)
1710 {
1711         struct smbcli_state *cli;
1712         const char *fname = "\\unlink.tst";
1713         int fnum;
1714         BOOL correct = True;
1715
1716         if (!torture_open_connection(&cli)) {
1717                 return False;
1718         }
1719
1720         printf("starting unlink test\n");
1721
1722         smbcli_unlink(cli->tree, fname);
1723
1724         cli->session->pid = 1;
1725
1726         printf("Opening a file\n");
1727
1728         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1729         if (fnum == -1) {
1730                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
1731                 return False;
1732         }
1733
1734         printf("Unlinking a open file\n");
1735
1736         if (NT_STATUS_IS_OK(smbcli_unlink(cli->tree, fname))) {
1737                 printf("error: server allowed unlink on an open file\n");
1738                 correct = False;
1739         } else {
1740                 correct = check_error(__LINE__, cli, ERRDOS, ERRbadshare, 
1741                                       NT_STATUS_SHARING_VIOLATION);
1742         }
1743
1744         smbcli_close(cli->tree, fnum);
1745         smbcli_unlink(cli->tree, fname);
1746
1747         if (!torture_close_connection(cli)) {
1748                 correct = False;
1749         }
1750
1751         printf("unlink test finished\n");
1752         
1753         return correct;
1754 }
1755
1756
1757 /*
1758 test the timing of deferred open requests
1759 */
1760 static BOOL run_deferopen(struct smbcli_state *cli, int dummy)
1761 {
1762         const char *fname = "\\defer_open_test.dat";
1763         int retries=4;
1764         int i = 0;
1765         BOOL correct = True;
1766
1767         if (retries <= 0) {
1768                 printf("failed to connect\n");
1769                 return False;
1770         }
1771
1772         printf("Testing deferred open requests.\n");
1773
1774         while (i < 4) {
1775                 int fnum = -1;
1776
1777                 do {
1778                         struct timeval tv_start, tv_end;
1779                         GetTimeOfDay(&tv_start);
1780                         fnum = smbcli_nt_create_full(cli->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS,
1781                                 FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE,
1782                                 NTCREATEX_DISP_OPEN_IF, 0, 0);
1783                         if (fnum != -1) {
1784                                 break;
1785                         }
1786                         GetTimeOfDay(&tv_end);
1787                         if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION)) {
1788                                 /* Sharing violation errors need to be 1 second apart. */
1789                                 int64_t tdif = usec_time_diff(&tv_end, &tv_start);
1790                                 if (tdif < 500000 || tdif > 1500000) {
1791                                         fprintf(stderr,"Timing incorrect %lld.%lld for share violation\n",
1792                                                 tdif / (int64_t)1000000, 
1793                                                 tdif % (int64_t)1000000);
1794                                 }
1795                         }
1796                 } while (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION));
1797
1798                 if (fnum == -1) {
1799                         fprintf(stderr,"Failed to open %s, error=%s\n", fname, smbcli_errstr(cli->tree));
1800                         return False;
1801                 }
1802
1803                 printf("pid %u open %d\n", getpid(), i);
1804
1805                 sleep(10);
1806                 i++;
1807                 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum))) {
1808                         fprintf(stderr,"Failed to close %s, error=%s\n", fname, smbcli_errstr(cli->tree));
1809                         return False;
1810                 }
1811                 sleep(2);
1812         }
1813
1814         if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
1815                 /* All until the last unlink will fail with sharing violation. */
1816                 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION)) {
1817                         printf("unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
1818                         correct = False;
1819                 }
1820         }
1821
1822         printf("deferred test finished\n");
1823         if (!torture_close_connection(cli)) {
1824                 correct = False;
1825         }
1826         return correct;
1827 }
1828
1829 /*
1830 test how many open files this server supports on the one socket
1831 */
1832 static BOOL run_maxfidtest(struct smbcli_state *cli, int dummy)
1833 {
1834 #define MAXFID_TEMPLATE "\\maxfid.%d.%d"
1835         char *fname;
1836         int fnums[0x11000], i;
1837         int retries=4;
1838         BOOL correct = True;
1839
1840         if (retries <= 0) {
1841                 printf("failed to connect\n");
1842                 return False;
1843         }
1844
1845         printf("Testing maximum number of open files\n");
1846
1847         for (i=0; i<0x11000; i++) {
1848                 asprintf(&fname, MAXFID_TEMPLATE, i,(int)getpid());
1849                 if ((fnums[i] = smbcli_open(cli->tree, fname, 
1850                                         O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) ==
1851                     -1) {
1852                         printf("open of %s failed (%s)\n", 
1853                                fname, smbcli_errstr(cli->tree));
1854                         printf("maximum fnum is %d\n", i);
1855                         break;
1856                 }
1857                 free(fname);
1858                 printf("%6d\r", i);
1859         }
1860         printf("%6d\n", i);
1861         i--;
1862
1863         printf("cleaning up\n");
1864         for (;i>=0;i--) {
1865                 asprintf(&fname, MAXFID_TEMPLATE, i,(int)getpid());
1866                 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[i]))) {
1867                         printf("Close of fnum %d failed - %s\n", fnums[i], smbcli_errstr(cli->tree));
1868                 }
1869                 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
1870                         printf("unlink of %s failed (%s)\n", 
1871                                fname, smbcli_errstr(cli->tree));
1872                         correct = False;
1873                 }
1874                 free(fname);
1875                 printf("%6d\r", i);
1876         }
1877         printf("%6d\n", 0);
1878
1879         printf("maxfid test finished\n");
1880         if (!torture_close_connection(cli)) {
1881                 correct = False;
1882         }
1883         return correct;
1884 #undef MAXFID_TEMPLATE
1885 }
1886
1887 /* send smb negprot commands, not reading the response */
1888 static BOOL run_negprot_nowait(int dummy)
1889 {
1890         int i;
1891         struct smbcli_state *cli, *cli2;
1892         BOOL correct = True;
1893
1894         printf("starting negprot nowait test\n");
1895
1896         cli = open_nbt_connection();
1897         if (!cli) {
1898                 return False;
1899         }
1900
1901         printf("Filling send buffer\n");
1902
1903         for (i=0;i<10000;i++) {
1904                 struct smbcli_request *req;
1905                 time_t t1 = time(NULL);
1906                 req = smb_negprot_send(cli->transport, PROTOCOL_NT1);
1907                 while (req->state == SMBCLI_REQUEST_SEND && time(NULL) < t1+5) {
1908                         smbcli_transport_process(cli->transport);
1909                 }
1910                 if (req->state == SMBCLI_REQUEST_ERROR) {
1911                         printf("Failed to fill pipe - %s\n", nt_errstr(req->status));
1912                         torture_close_connection(cli);
1913                         return correct;
1914                 }
1915                 if (req->state == SMBCLI_REQUEST_SEND) {
1916                         break;
1917                 }
1918         }
1919
1920         if (i == 10000) {
1921                 printf("send buffer failed to fill\n");
1922                 if (!torture_close_connection(cli)) {
1923                         correct = False;
1924                 }
1925                 return correct;
1926         }
1927
1928         printf("send buffer filled after %d requests\n", i);
1929
1930         printf("Opening secondary connection\n");
1931         if (!torture_open_connection(&cli2)) {
1932                 return False;
1933         }
1934
1935         if (!torture_close_connection(cli)) {
1936                 correct = False;
1937         }
1938
1939         if (!torture_close_connection(cli2)) {
1940                 correct = False;
1941         }
1942
1943         printf("finished negprot nowait test\n");
1944
1945         return correct;
1946 }
1947
1948
1949 /*
1950   This checks how the getatr calls works
1951 */
1952 static BOOL run_attrtest(int dummy)
1953 {
1954         struct smbcli_state *cli;
1955         int fnum;
1956         time_t t, t2;
1957         const char *fname = "\\attrib123456789.tst";
1958         BOOL correct = True;
1959
1960         printf("starting attrib test\n");
1961
1962         if (!torture_open_connection(&cli)) {
1963                 return False;
1964         }
1965
1966         smbcli_unlink(cli->tree, fname);
1967         fnum = smbcli_open(cli->tree, fname, 
1968                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1969         smbcli_close(cli->tree, fnum);
1970
1971         if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
1972                 printf("getatr failed (%s)\n", smbcli_errstr(cli->tree));
1973                 correct = False;
1974         }
1975
1976         printf("New file time is %s", ctime(&t));
1977
1978         if (abs(t - time(NULL)) > 60*60*24*10) {
1979                 printf("ERROR: SMBgetatr bug. time is %s",
1980                        ctime(&t));
1981                 t = time(NULL);
1982                 correct = False;
1983         }
1984
1985         t2 = t-60*60*24; /* 1 day ago */
1986
1987         printf("Setting file time to %s", ctime(&t2));
1988
1989         if (NT_STATUS_IS_ERR(smbcli_setatr(cli->tree, fname, 0, t2))) {
1990                 printf("setatr failed (%s)\n", smbcli_errstr(cli->tree));
1991                 correct = True;
1992         }
1993
1994         if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
1995                 printf("getatr failed (%s)\n", smbcli_errstr(cli->tree));
1996                 correct = True;
1997         }
1998
1999         printf("Retrieved file time as %s", ctime(&t));
2000
2001         if (t != t2) {
2002                 printf("ERROR: getatr/setatr bug. times are\n%s",
2003                        ctime(&t));
2004                 printf("%s", ctime(&t2));
2005                 correct = True;
2006         }
2007
2008         smbcli_unlink(cli->tree, fname);
2009
2010         if (!torture_close_connection(cli)) {
2011                 correct = False;
2012         }
2013
2014         printf("attrib test finished\n");
2015
2016         return correct;
2017 }
2018
2019
2020 /*
2021   This checks a couple of trans2 calls
2022 */
2023 static BOOL run_trans2test(int dummy)
2024 {
2025         struct smbcli_state *cli;
2026         int fnum;
2027         size_t size;
2028         time_t c_time, a_time, m_time, w_time, m_time2;
2029         const char *fname = "\\trans2.tst";
2030         const char *dname = "\\trans2";
2031         const char *fname2 = "\\trans2\\trans2.tst";
2032         const char *pname;
2033         BOOL correct = True;
2034
2035         printf("starting trans2 test\n");
2036
2037         if (!torture_open_connection(&cli)) {
2038                 return False;
2039         }
2040
2041         smbcli_unlink(cli->tree, fname);
2042
2043         printf("Testing qfileinfo\n");
2044         
2045         fnum = smbcli_open(cli->tree, fname, 
2046                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2047         if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, NULL, &size, &c_time, &a_time, &m_time,
2048                            NULL, NULL))) {
2049                 printf("ERROR: qfileinfo failed (%s)\n", smbcli_errstr(cli->tree));
2050                 correct = False;
2051         }
2052
2053         printf("Testing NAME_INFO\n");
2054
2055         if (NT_STATUS_IS_ERR(smbcli_qfilename(cli->tree, fnum, &pname))) {
2056                 printf("ERROR: qfilename failed (%s)\n", smbcli_errstr(cli->tree));
2057                 correct = False;
2058         }
2059
2060         if (!pname || strcmp(pname, fname)) {
2061                 printf("qfilename gave different name? [%s] [%s]\n",
2062                        fname, pname);
2063                 correct = False;
2064         }
2065
2066         smbcli_close(cli->tree, fnum);
2067         smbcli_unlink(cli->tree, fname);
2068
2069         fnum = smbcli_open(cli->tree, fname, 
2070                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2071         if (fnum == -1) {
2072                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
2073                 return False;
2074         }
2075         smbcli_close(cli->tree, fnum);
2076
2077         printf("Checking for sticky create times\n");
2078
2079         if (NT_STATUS_IS_ERR(smbcli_qpathinfo(cli->tree, fname, &c_time, &a_time, &m_time, &size, NULL))) {
2080                 printf("ERROR: qpathinfo failed (%s)\n", smbcli_errstr(cli->tree));
2081                 correct = False;
2082         } else {
2083                 if (c_time != m_time) {
2084                         printf("create time=%s", ctime(&c_time));
2085                         printf("modify time=%s", ctime(&m_time));
2086                         printf("This system appears to have sticky create times\n");
2087                 }
2088                 if (a_time % (60*60) == 0) {
2089                         printf("access time=%s", ctime(&a_time));
2090                         printf("This system appears to set a midnight access time\n");
2091                         correct = False;
2092                 }
2093
2094                 if (abs(m_time - time(NULL)) > 60*60*24*7) {
2095                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
2096                         correct = False;
2097                 }
2098         }
2099
2100
2101         smbcli_unlink(cli->tree, fname);
2102         fnum = smbcli_open(cli->tree, fname, 
2103                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2104         smbcli_close(cli->tree, fnum);
2105         if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, fname, &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
2106                 printf("ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
2107                 correct = False;
2108         } else {
2109                 if (w_time < 60*60*24*2) {
2110                         printf("write time=%s", ctime(&w_time));
2111                         printf("This system appears to set a initial 0 write time\n");
2112                         correct = False;
2113                 }
2114         }
2115
2116         smbcli_unlink(cli->tree, fname);
2117
2118
2119         /* check if the server updates the directory modification time
2120            when creating a new file */
2121         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) {
2122                 printf("ERROR: mkdir failed (%s)\n", smbcli_errstr(cli->tree));
2123                 correct = False;
2124         }
2125         sleep(3);
2126         if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
2127                 printf("ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
2128                 correct = False;
2129         }
2130
2131         fnum = smbcli_open(cli->tree, fname2, 
2132                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2133         smbcli_write(cli->tree, fnum,  0, (char *)&fnum, 0, sizeof(fnum));
2134         smbcli_close(cli->tree, fnum);
2135         if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time2, &w_time, &size, NULL, NULL))) {
2136                 printf("ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
2137                 correct = False;
2138         } else {
2139                 if (m_time2 == m_time) {
2140                         printf("This system does not update directory modification times\n");
2141                         correct = False;
2142                 }
2143         }
2144         smbcli_unlink(cli->tree, fname2);
2145         smbcli_rmdir(cli->tree, dname);
2146
2147         if (!torture_close_connection(cli)) {
2148                 correct = False;
2149         }
2150
2151         printf("trans2 test finished\n");
2152
2153         return correct;
2154 }
2155
2156 /*
2157   Test delete on close semantics.
2158  */
2159 static BOOL run_deletetest(int dummy)
2160 {
2161         struct smbcli_state *cli1;
2162         struct smbcli_state *cli2 = NULL;
2163         const char *fname = "\\delete.file";
2164         int fnum1 = -1;
2165         int fnum2 = -1;
2166         BOOL correct = True;
2167         
2168         printf("starting delete test\n");
2169         
2170         if (!torture_open_connection(&cli1)) {
2171                 return False;
2172         }
2173         
2174         /* Test 1 - this should delete the file on close. */
2175         
2176         smbcli_setatr(cli1->tree, fname, 0, 0);
2177         smbcli_unlink(cli1->tree, fname);
2178         
2179         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
2180                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 
2181                                    NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2182         
2183         if (fnum1 == -1) {
2184                 printf("[1] open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2185                 correct = False;
2186                 goto fail;
2187         }
2188         
2189         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2190                 printf("[1] close failed (%s)\n", smbcli_errstr(cli1->tree));
2191                 correct = False;
2192                 goto fail;
2193         }
2194
2195         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
2196         if (fnum1 != -1) {
2197                 printf("[1] open of %s succeeded (should fail)\n", fname);
2198                 correct = False;
2199                 goto fail;
2200         }
2201         
2202         printf("first delete on close test succeeded.\n");
2203         
2204         /* Test 2 - this should delete the file on close. */
2205         
2206         smbcli_setatr(cli1->tree, fname, 0, 0);
2207         smbcli_unlink(cli1->tree, fname);
2208         
2209         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS,
2210                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, 
2211                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2212         
2213         if (fnum1 == -1) {
2214                 printf("[2] open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2215                 correct = False;
2216                 goto fail;
2217         }
2218         
2219         if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2220                 printf("[2] setting delete_on_close failed (%s)\n", smbcli_errstr(cli1->tree));
2221                 correct = False;
2222                 goto fail;
2223         }
2224         
2225         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2226                 printf("[2] close failed (%s)\n", smbcli_errstr(cli1->tree));
2227                 correct = False;
2228                 goto fail;
2229         }
2230         
2231         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2232         if (fnum1 != -1) {
2233                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
2234                 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2235                         printf("[2] close failed (%s)\n", smbcli_errstr(cli1->tree));
2236                         correct = False;
2237                         goto fail;
2238                 }
2239                 smbcli_unlink(cli1->tree, fname);
2240         } else
2241                 printf("second delete on close test succeeded.\n");
2242         
2243         /* Test 3 - ... */
2244         smbcli_setatr(cli1->tree, fname, 0, 0);
2245         smbcli_unlink(cli1->tree, fname);
2246
2247         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
2248                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2249
2250         if (fnum1 == -1) {
2251                 printf("[3] open - 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2252                 correct = False;
2253                 goto fail;
2254         }
2255
2256         /* This should fail with a sharing violation - open for delete is only compatible
2257            with SHARE_DELETE. */
2258
2259         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
2260                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
2261                                    NTCREATEX_DISP_OPEN, 0, 0);
2262
2263         if (fnum2 != -1) {
2264                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
2265                 correct = False;
2266                 goto fail;
2267         }
2268
2269         /* This should succeed. */
2270
2271         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
2272                         NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN, 0, 0);
2273
2274         if (fnum2 == -1) {
2275                 printf("[3] open  - 2 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2276                 correct = False;
2277                 goto fail;
2278         }
2279
2280         if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2281                 printf("[3] setting delete_on_close failed (%s)\n", smbcli_errstr(cli1->tree));
2282                 correct = False;
2283                 goto fail;
2284         }
2285         
2286         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2287                 printf("[3] close 1 failed (%s)\n", smbcli_errstr(cli1->tree));
2288                 correct = False;
2289                 goto fail;
2290         }
2291         
2292         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
2293                 printf("[3] close 2 failed (%s)\n", smbcli_errstr(cli1->tree));
2294                 correct = False;
2295                 goto fail;
2296         }
2297         
2298         /* This should fail - file should no longer be there. */
2299
2300         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2301         if (fnum1 != -1) {
2302                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
2303                 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2304                         printf("[3] close failed (%s)\n", smbcli_errstr(cli1->tree));
2305                 }
2306                 smbcli_unlink(cli1->tree, fname);
2307                 correct = False;
2308                 goto fail;
2309         } else
2310                 printf("third delete on close test succeeded.\n");
2311
2312         /* Test 4 ... */
2313         smbcli_setatr(cli1->tree, fname, 0, 0);
2314         smbcli_unlink(cli1->tree, fname);
2315
2316         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
2317                                    SA_RIGHT_FILE_READ_DATA  | 
2318                                    SA_RIGHT_FILE_WRITE_DATA |
2319                                    STD_RIGHT_DELETE_ACCESS,
2320                                    FILE_ATTRIBUTE_NORMAL, 
2321                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
2322                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2323                                                                 
2324         if (fnum1 == -1) {
2325                 printf("[4] open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2326                 correct = False;
2327                 goto fail;
2328         }
2329
2330         /* This should succeed. */
2331         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ,
2332                                    FILE_ATTRIBUTE_NORMAL, 
2333                                    NTCREATEX_SHARE_ACCESS_READ  | 
2334                                    NTCREATEX_SHARE_ACCESS_WRITE |
2335                                    NTCREATEX_SHARE_ACCESS_DELETE, 
2336                                    NTCREATEX_DISP_OPEN, 0, 0);
2337         if (fnum2 == -1) {
2338                 printf("[4] open  - 2 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2339                 correct = False;
2340                 goto fail;
2341         }
2342         
2343         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
2344                 printf("[4] close - 1 failed (%s)\n", smbcli_errstr(cli1->tree));
2345                 correct = False;
2346                 goto fail;
2347         }
2348         
2349         if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2350                 printf("[4] setting delete_on_close failed (%s)\n", smbcli_errstr(cli1->tree));
2351                 correct = False;
2352                 goto fail;
2353         }
2354         
2355         /* This should fail - no more opens once delete on close set. */
2356         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ,
2357                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
2358                                    NTCREATEX_DISP_OPEN, 0, 0);
2359         if (fnum2 != -1) {
2360                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
2361                 correct = False;
2362                 goto fail;
2363         } else
2364                 printf("fourth delete on close test succeeded.\n");
2365         
2366         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2367                 printf("[4] close - 2 failed (%s)\n", smbcli_errstr(cli1->tree));
2368                 correct = False;
2369                 goto fail;
2370         }
2371         
2372         /* Test 5 ... */
2373         smbcli_setatr(cli1->tree, fname, 0, 0);
2374         smbcli_unlink(cli1->tree, fname);
2375         
2376         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2377         if (fnum1 == -1) {
2378                 printf("[5] open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2379                 correct = False;
2380                 goto fail;
2381         }
2382
2383         /* This should fail - only allowed on NT opens with DELETE access. */
2384
2385         if (NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2386                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
2387                 correct = False;
2388                 goto fail;
2389         }
2390
2391         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2392                 printf("[5] close - 2 failed (%s)\n", smbcli_errstr(cli1->tree));
2393                 correct = False;
2394                 goto fail;
2395         }
2396         
2397         printf("fifth delete on close test succeeded.\n");
2398         
2399         /* Test 6 ... */
2400         smbcli_setatr(cli1->tree, fname, 0, 0);
2401         smbcli_unlink(cli1->tree, fname);
2402         
2403         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
2404                                    SA_RIGHT_FILE_READ_DATA | SA_RIGHT_FILE_WRITE_DATA,
2405                                    FILE_ATTRIBUTE_NORMAL, 
2406                                    NTCREATEX_SHARE_ACCESS_READ  |
2407                                    NTCREATEX_SHARE_ACCESS_WRITE |
2408                                    NTCREATEX_SHARE_ACCESS_DELETE,
2409                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2410         
2411         if (fnum1 == -1) {
2412                 printf("[6] open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2413                 correct = False;
2414                 goto fail;
2415         }
2416         
2417         /* This should fail - only allowed on NT opens with DELETE access. */
2418         
2419         if (NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2420                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
2421                 correct = False;
2422                 goto fail;
2423         }
2424
2425         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2426                 printf("[6] close - 2 failed (%s)\n", smbcli_errstr(cli1->tree));
2427                 correct = False;
2428                 goto fail;
2429         }
2430
2431         printf("sixth delete on close test succeeded.\n");
2432         
2433         /* Test 7 ... */
2434         smbcli_setatr(cli1->tree, fname, 0, 0);
2435         smbcli_unlink(cli1->tree, fname);
2436         
2437         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
2438                                    SA_RIGHT_FILE_READ_DATA  | 
2439                                    SA_RIGHT_FILE_WRITE_DATA |
2440                                    STD_RIGHT_DELETE_ACCESS,
2441                                    FILE_ATTRIBUTE_NORMAL, 0, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2442                                                                 
2443         if (fnum1 == -1) {
2444                 printf("[7] open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2445                 correct = False;
2446                 goto fail;
2447         }
2448
2449         if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2450                 printf("[7] setting delete_on_close on file failed !\n");
2451                 correct = False;
2452                 goto fail;
2453         }
2454         
2455         if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, False))) {
2456                 printf("[7] unsetting delete_on_close on file failed !\n");
2457                 correct = False;
2458                 goto fail;
2459         }
2460
2461         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2462                 printf("[7] close - 2 failed (%s)\n", smbcli_errstr(cli1->tree));
2463                 correct = False;
2464                 goto fail;
2465         }
2466         
2467         /* This next open should succeed - we reset the flag. */
2468         
2469         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2470         if (fnum1 == -1) {
2471                 printf("[5] open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2472                 correct = False;
2473                 goto fail;
2474         }
2475
2476         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2477                 printf("[7] close - 2 failed (%s)\n", smbcli_errstr(cli1->tree));
2478                 correct = False;
2479                 goto fail;
2480         }
2481
2482         printf("seventh delete on close test succeeded.\n");
2483         
2484         /* Test 7 ... */
2485         smbcli_setatr(cli1->tree, fname, 0, 0);
2486         smbcli_unlink(cli1->tree, fname);
2487         
2488         if (!torture_open_connection(&cli2)) {
2489                 printf("[8] failed to open second connection.\n");
2490                 correct = False;
2491                 goto fail;
2492         }
2493
2494         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|STD_RIGHT_DELETE_ACCESS,
2495                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
2496                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2497         
2498         if (fnum1 == -1) {
2499                 printf("[8] open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2500                 correct = False;
2501                 goto fail;
2502         }
2503
2504         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|STD_RIGHT_DELETE_ACCESS,
2505                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
2506                                    NTCREATEX_DISP_OPEN, 0, 0);
2507         
2508         if (fnum2 == -1) {
2509                 printf("[8] open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2510                 correct = False;
2511                 goto fail;
2512         }
2513
2514         if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2515                 printf("[8] setting delete_on_close on file failed !\n");
2516                 correct = False;
2517                 goto fail;
2518         }
2519         
2520         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2521                 printf("[8] close - 1 failed (%s)\n", smbcli_errstr(cli1->tree));
2522                 correct = False;
2523                 goto fail;
2524         }
2525
2526         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
2527                 printf("[8] close - 2 failed (%s)\n", smbcli_errstr(cli2->tree));
2528                 correct = False;
2529                 goto fail;
2530         }
2531
2532         /* This should fail.. */
2533         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2534         if (fnum1 != -1) {
2535                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
2536                 goto fail;
2537                 correct = False;
2538         } else
2539                 printf("eighth delete on close test succeeded.\n");
2540
2541         /* This should fail - we need to set DELETE_ACCESS. */
2542         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA,
2543                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2544         
2545         if (fnum1 != -1) {
2546                 printf("[9] open of %s succeeded should have failed!\n", fname);
2547                 correct = False;
2548                 goto fail;
2549         }
2550
2551         printf("ninth delete on close test succeeded.\n");
2552
2553         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|STD_RIGHT_DELETE_ACCESS,
2554                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2555         if (fnum1 == -1) {
2556                 printf("[10] open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2557                 correct = False;
2558                 goto fail;
2559         }
2560
2561         /* This should delete the file. */
2562         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2563                 printf("[10] close failed (%s)\n", smbcli_errstr(cli1->tree));
2564                 correct = False;
2565                 goto fail;
2566         }
2567
2568         /* This should fail.. */
2569         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2570         if (fnum1 != -1) {
2571                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
2572                 goto fail;
2573                 correct = False;
2574         } else
2575                 printf("tenth delete on close test succeeded.\n");
2576         printf("finished delete test\n");
2577
2578   fail:
2579         /* FIXME: This will crash if we aborted before cli2 got
2580          * intialized, because these functions don't handle
2581          * uninitialized connections. */
2582                 
2583         smbcli_close(cli1->tree, fnum1);
2584         smbcli_close(cli1->tree, fnum2);
2585         smbcli_setatr(cli1->tree, fname, 0, 0);
2586         smbcli_unlink(cli1->tree, fname);
2587
2588         if (!torture_close_connection(cli1)) {
2589                 correct = False;
2590         }
2591         if (!torture_close_connection(cli2)) {
2592                 correct = False;
2593         }
2594         return correct;
2595 }
2596
2597
2598 /*
2599   print out server properties
2600  */
2601 static BOOL run_properties(int dummy)
2602 {
2603         struct smbcli_state *cli;
2604         BOOL correct = True;
2605         
2606         printf("starting properties test\n");
2607         
2608         ZERO_STRUCT(cli);
2609
2610         if (!torture_open_connection(&cli)) {
2611                 return False;
2612         }
2613         
2614         d_printf("Capabilities 0x%08x\n", cli->transport->negotiate.capabilities);
2615
2616         if (!torture_close_connection(cli)) {
2617                 correct = False;
2618         }
2619
2620         return correct;
2621 }
2622
2623
2624
2625 /* FIRST_DESIRED_ACCESS   0xf019f */
2626 #define FIRST_DESIRED_ACCESS   SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|SA_RIGHT_FILE_APPEND_DATA|\
2627                                SA_RIGHT_FILE_READ_EA|                           /* 0xf */ \
2628                                SA_RIGHT_FILE_WRITE_EA|SA_RIGHT_FILE_READ_ATTRIBUTES|     /* 0x90 */ \
2629                                SA_RIGHT_FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
2630                                STD_RIGHT_DELETE_ACCESS|STD_RIGHT_READ_CONTROL_ACCESS|\
2631                                STD_RIGHT_WRITE_DAC_ACCESS|STD_RIGHT_WRITE_OWNER_ACCESS     /* 0xf0000 */
2632 /* SECOND_DESIRED_ACCESS  0xe0080 */
2633 #define SECOND_DESIRED_ACCESS  SA_RIGHT_FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
2634                                STD_RIGHT_READ_CONTROL_ACCESS|STD_RIGHT_WRITE_DAC_ACCESS|\
2635                                STD_RIGHT_WRITE_OWNER_ACCESS                      /* 0xe0000 */
2636
2637 #if 0
2638 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
2639                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
2640                                SA_RIGHT_FILE_READ_DATA|\
2641                                WRITE_OWNER_ACCESS                      /* */
2642 #endif
2643
2644 /*
2645   Test ntcreate calls made by xcopy
2646  */
2647 static BOOL run_xcopy(int dummy)
2648 {
2649         struct smbcli_state *cli1;
2650         const char *fname = "\\test.txt";
2651         BOOL correct = True;
2652         int fnum1, fnum2;
2653
2654         printf("starting xcopy test\n");
2655         
2656         if (!torture_open_connection(&cli1)) {
2657                 return False;
2658         }
2659         
2660         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
2661                                    FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
2662                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 
2663                                    0x4044, 0);
2664
2665         if (fnum1 == -1) {
2666                 printf("First open failed - %s\n", smbcli_errstr(cli1->tree));
2667                 return False;
2668         }
2669
2670         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
2671                                    SECOND_DESIRED_ACCESS, 0,
2672                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN, 
2673                                    0x200000, 0);
2674         if (fnum2 == -1) {
2675                 printf("second open failed - %s\n", smbcli_errstr(cli1->tree));
2676                 return False;
2677         }
2678         
2679         if (!torture_close_connection(cli1)) {
2680                 correct = False;
2681         }
2682         
2683         return correct;
2684 }
2685
2686 /*
2687   Test rename on files open with share delete and no share delete.
2688  */
2689 static BOOL run_rename(int dummy)
2690 {
2691         struct smbcli_state *cli1;
2692         const char *fname = "\\test.txt";
2693         const char *fname1 = "\\test1.txt";
2694         BOOL correct = True;
2695         int fnum1;
2696
2697         printf("starting rename test\n");
2698         
2699         if (!torture_open_connection(&cli1)) {
2700                 return False;
2701         }
2702         
2703         smbcli_unlink(cli1->tree, fname);
2704         smbcli_unlink(cli1->tree, fname1);
2705         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
2706                                    NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2707
2708         if (fnum1 == -1) {
2709                 printf("First open failed - %s\n", smbcli_errstr(cli1->tree));
2710                 return False;
2711         }
2712
2713         if (NT_STATUS_IS_ERR(smbcli_rename(cli1->tree, fname, fname1))) {
2714                 printf("First rename failed (this is correct) - %s\n", smbcli_errstr(cli1->tree));
2715         } else {
2716                 printf("First rename succeeded - this should have failed !\n");
2717                 correct = False;
2718         }
2719
2720         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2721                 printf("close - 1 failed (%s)\n", smbcli_errstr(cli1->tree));
2722                 return False;
2723         }
2724
2725         smbcli_unlink(cli1->tree, fname);
2726         smbcli_unlink(cli1->tree, fname1);
2727         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
2728                                    NTCREATEX_SHARE_ACCESS_DELETE|NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2729
2730         if (fnum1 == -1) {
2731                 printf("Second open failed - %s\n", smbcli_errstr(cli1->tree));
2732                 return False;
2733         }
2734
2735         if (NT_STATUS_IS_ERR(smbcli_rename(cli1->tree, fname, fname1))) {
2736                 printf("Second rename failed - this should have succeeded - %s\n", smbcli_errstr(cli1->tree));
2737                 correct = False;
2738         } else {
2739                 printf("Second rename succeeded\n");
2740         }
2741
2742         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2743                 printf("close - 2 failed (%s)\n", smbcli_errstr(cli1->tree));
2744                 return False;
2745         }
2746
2747         smbcli_unlink(cli1->tree, fname);
2748         smbcli_unlink(cli1->tree, fname1);
2749
2750         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_READ_CONTROL_ACCESS, FILE_ATTRIBUTE_NORMAL,
2751                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2752
2753         if (fnum1 == -1) {
2754                 printf("Third open failed - %s\n", smbcli_errstr(cli1->tree));
2755                 return False;
2756         }
2757
2758
2759         if (NT_STATUS_IS_ERR(smbcli_rename(cli1->tree, fname, fname1))) {
2760                 printf("Third rename failed - this should have succeeded - %s\n", smbcli_errstr(cli1->tree));
2761                 correct = False;
2762         } else {
2763                 printf("Third rename succeeded\n");
2764         }
2765
2766         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2767                 printf("close - 3 failed (%s)\n", smbcli_errstr(cli1->tree));
2768                 return False;
2769         }
2770
2771         smbcli_unlink(cli1->tree, fname);
2772         smbcli_unlink(cli1->tree, fname1);
2773
2774         if (!torture_close_connection(cli1)) {
2775                 correct = False;
2776         }
2777         
2778         return correct;
2779 }
2780
2781
2782 /*
2783   see how many RPC pipes we can open at once
2784 */
2785 static BOOL run_pipe_number(int dummy)
2786 {
2787         struct smbcli_state *cli1;
2788         const char *pipe_name = "\\WKSSVC";
2789         int fnum;
2790         int num_pipes = 0;
2791
2792         printf("starting pipenumber test\n");
2793         if (!torture_open_connection(&cli1)) {
2794                 return False;
2795         }
2796
2797         while(1) {
2798                 fnum = smbcli_nt_create_full(cli1->tree, pipe_name, 0, SA_RIGHT_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
2799                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OPEN_IF, 0, 0);
2800
2801                 if (fnum == -1) {
2802                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, smbcli_errstr(cli1->tree));
2803                         break;
2804                 }
2805                 num_pipes++;
2806                 printf("%d\r", num_pipes);
2807                 fflush(stdout);
2808         }
2809
2810         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
2811         torture_close_connection(cli1);
2812         return True;
2813 }
2814
2815
2816
2817
2818 /*
2819   open N connections to the server and just hold them open
2820   used for testing performance when there are N idle users
2821   already connected
2822  */
2823  static BOOL torture_holdcon(int dummy)
2824 {
2825         int i;
2826         struct smbcli_state **cli;
2827         int num_dead = 0;
2828
2829         printf("Opening %d connections\n", torture_numops);
2830         
2831         cli = malloc(sizeof(struct smbcli_state *) * torture_numops);
2832
2833         for (i=0;i<torture_numops;i++) {
2834                 if (!torture_open_connection(&cli[i])) {
2835                         return False;
2836                 }
2837                 printf("opened %d connections\r", i);
2838                 fflush(stdout);
2839         }
2840
2841         printf("\nStarting pings\n");
2842
2843         while (1) {
2844                 for (i=0;i<torture_numops;i++) {
2845                         NTSTATUS status;
2846                         if (cli[i]) {
2847                                 status = smbcli_chkpath(cli[i]->tree, "\\");
2848                                 if (!NT_STATUS_IS_OK(status)) {
2849                                         printf("Connection %d is dead\n", i);
2850                                         cli[i] = NULL;
2851                                         num_dead++;
2852                                 }
2853                                 usleep(100);
2854                         }
2855                 }
2856
2857                 if (num_dead == torture_numops) {
2858                         printf("All connections dead - finishing\n");
2859                         break;
2860                 }
2861
2862                 printf(".");
2863                 fflush(stdout);
2864         }
2865
2866         return True;
2867 }
2868
2869 /*
2870   Try with a wrong vuid and check error message.
2871  */
2872
2873 static BOOL run_vuidtest(int dummy)
2874 {
2875         struct smbcli_state *cli;
2876         const char *fname = "\\vuid.tst";
2877         int fnum;
2878         size_t size;
2879         time_t c_time, a_time, m_time;
2880         BOOL correct = True;
2881
2882         uint16_t orig_vuid;
2883         NTSTATUS result;
2884
2885         printf("starting vuid test\n");
2886
2887         if (!torture_open_connection(&cli)) {
2888                 return False;
2889         }
2890
2891         smbcli_unlink(cli->tree, fname);
2892
2893         fnum = smbcli_open(cli->tree, fname, 
2894                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2895
2896         orig_vuid = cli->session->vuid;
2897
2898         cli->session->vuid += 1234;
2899
2900         printf("Testing qfileinfo with wrong vuid\n");
2901         
2902         if (NT_STATUS_IS_OK(result = smbcli_qfileinfo(cli->tree, fnum, NULL,
2903                                                    &size, &c_time, &a_time,
2904                                                    &m_time, NULL, NULL))) {
2905                 printf("ERROR: qfileinfo passed with wrong vuid\n");
2906                 correct = False;
2907         }
2908
2909         if ( (cli->transport->error.etype != ETYPE_DOS) ||
2910              (cli->transport->error.e.dos.eclass != ERRSRV) ||
2911              (cli->transport->error.e.dos.ecode != ERRbaduid) ) {
2912                 printf("ERROR: qfileinfo should have returned DOS error "
2913                        "ERRSRV:ERRbaduid\n  but returned %s\n",
2914                        smbcli_errstr(cli->tree));
2915                 correct = False;
2916         }
2917
2918         cli->session->vuid -= 1234;
2919
2920         if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum))) {
2921                 printf("close failed (%s)\n", smbcli_errstr(cli->tree));
2922                 correct = False;
2923         }
2924
2925         smbcli_unlink(cli->tree, fname);
2926
2927         if (!torture_close_connection(cli)) {
2928                 correct = False;
2929         }
2930
2931         printf("vuid test finished\n");
2932
2933         return correct;
2934 }
2935
2936 /*
2937   Test open mode returns on read-only files.
2938  */
2939  static BOOL run_opentest(int dummy)
2940 {
2941         static struct smbcli_state *cli1;
2942         static struct smbcli_state *cli2;
2943         const char *fname = "\\readonly.file";
2944         int fnum1, fnum2;
2945         char buf[20];
2946         size_t fsize;
2947         BOOL correct = True;
2948         char *tmp_path;
2949         int failures = 0;
2950
2951         printf("starting open test\n");
2952         
2953         if (!torture_open_connection(&cli1)) {
2954                 return False;
2955         }
2956         
2957         smbcli_setatr(cli1->tree, fname, 0, 0);
2958         smbcli_unlink(cli1->tree, fname);
2959         
2960         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
2961         if (fnum1 == -1) {
2962                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2963                 return False;
2964         }
2965
2966         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
2967                 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
2968                 return False;
2969         }
2970         
2971         if (NT_STATUS_IS_ERR(smbcli_setatr(cli1->tree, fname, FILE_ATTRIBUTE_READONLY, 0))) {
2972                 printf("smbcli_setatr failed (%s)\n", smbcli_errstr(cli1->tree));
2973                 CHECK_MAX_FAILURES(error_test1);
2974                 return False;
2975         }
2976         
2977         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
2978         if (fnum1 == -1) {
2979                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
2980                 CHECK_MAX_FAILURES(error_test1);
2981                 return False;
2982         }
2983         
2984         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
2985         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
2986         
2987         if (check_error(__LINE__, cli1, ERRDOS, ERRnoaccess, 
2988                         NT_STATUS_ACCESS_DENIED)) {
2989                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
2990         }
2991         
2992         printf("finished open test 1\n");
2993 error_test1:
2994         smbcli_close(cli1->tree, fnum1);
2995         
2996         /* Now try not readonly and ensure ERRbadshare is returned. */
2997         
2998         smbcli_setatr(cli1->tree, fname, 0, 0);
2999         
3000         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
3001         if (fnum1 == -1) {
3002                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
3003                 return False;
3004         }
3005         
3006         /* This will fail - but the error should be ERRshare. */
3007         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
3008         
3009         if (check_error(__LINE__, cli1, ERRDOS, ERRbadshare, 
3010                         NT_STATUS_SHARING_VIOLATION)) {
3011                 printf("correct error code ERRDOS/ERRbadshare returned\n");
3012         }
3013         
3014         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
3015                 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
3016                 return False;
3017         }
3018         
3019         smbcli_unlink(cli1->tree, fname);
3020         
3021         printf("finished open test 2\n");
3022         
3023         /* Test truncate open disposition on file opened for read. */
3024         
3025         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
3026         if (fnum1 == -1) {
3027                 printf("(3) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
3028                 return False;
3029         }
3030         
3031         /* write 20 bytes. */
3032         
3033         memset(buf, '\0', 20);
3034
3035         if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
3036                 printf("write failed (%s)\n", smbcli_errstr(cli1->tree));
3037                 correct = False;
3038         }
3039
3040         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
3041                 printf("(3) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
3042                 return False;
3043         }
3044         
3045         /* Ensure size == 20. */
3046         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
3047                 printf("(3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
3048                 CHECK_MAX_FAILURES(error_test3);
3049                 return False;
3050         }
3051         
3052         if (fsize != 20) {
3053                 printf("(3) file size != 20\n");
3054                 CHECK_MAX_FAILURES(error_test3);
3055                 return False;
3056         }
3057
3058         /* Now test if we can truncate a file opened for readonly. */
3059         
3060         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY|O_TRUNC, DENY_NONE);
3061         if (fnum1 == -1) {
3062                 printf("(3) open (2) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
3063                 CHECK_MAX_FAILURES(error_test3);
3064                 return False;
3065         }
3066         
3067         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
3068                 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
3069                 return False;
3070         }
3071
3072         /* Ensure size == 0. */
3073         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
3074                 printf("(3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
3075                 CHECK_MAX_FAILURES(error_test3);
3076                 return False;
3077         }
3078
3079         if (fsize != 0) {
3080                 printf("(3) file size != 0\n");
3081                 CHECK_MAX_FAILURES(error_test3);
3082                 return False;
3083         }
3084         printf("finished open test 3\n");
3085 error_test3:    
3086         smbcli_unlink(cli1->tree, fname);
3087
3088
3089         printf("testing ctemp\n");
3090         fnum1 = smbcli_ctemp(cli1->tree, "\\", &tmp_path);
3091         if (fnum1 == -1) {
3092                 printf("ctemp failed (%s)\n", smbcli_errstr(cli1->tree));
3093                 CHECK_MAX_FAILURES(error_test4);
3094                 return False;
3095         }
3096         printf("ctemp gave path %s\n", tmp_path);
3097         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
3098                 printf("close of temp failed (%s)\n", smbcli_errstr(cli1->tree));
3099         }
3100         if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, tmp_path))) {
3101                 printf("unlink of temp failed (%s)\n", smbcli_errstr(cli1->tree));
3102         }
3103 error_test4:    
3104         /* Test the non-io opens... */
3105
3106         if (!torture_open_connection(&cli2)) {
3107                 return False;
3108         }
3109         
3110         smbcli_setatr(cli2->tree, fname, 0, 0);
3111         smbcli_unlink(cli2->tree, fname);
3112         
3113         printf("TEST #1 testing 2 non-io opens (no delete)\n");
3114         
3115         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3116                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3117
3118         if (fnum1 == -1) {
3119                 printf("test 1 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
3120                 CHECK_MAX_FAILURES(error_test10);
3121                 return False;
3122         }
3123
3124         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3125                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3126         if (fnum2 == -1) {
3127                 printf("test 1 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
3128                 CHECK_MAX_FAILURES(error_test10);
3129                 return False;
3130         }
3131
3132         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
3133                 printf("test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
3134                 return False;
3135         }
3136         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
3137                 printf("test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
3138                 return False;
3139         }
3140
3141         printf("non-io open test #1 passed.\n");
3142 error_test10:
3143         smbcli_unlink(cli1->tree, fname);
3144
3145         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
3146         
3147         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3148                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3149
3150         if (fnum1 == -1) {
3151                 printf("test 2 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
3152                 CHECK_MAX_FAILURES(error_test20);
3153                 return False;
3154         }
3155
3156         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3157                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3158
3159         if (fnum2 == -1) {
3160                 printf("test 2 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
3161                 CHECK_MAX_FAILURES(error_test20);
3162                 return False;
3163         }
3164
3165         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
3166                 printf("test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
3167                 return False;
3168         }
3169         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
3170                 printf("test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
3171                 return False;
3172         }
3173
3174         printf("non-io open test #2 passed.\n");
3175 error_test20:
3176         smbcli_unlink(cli1->tree, fname);
3177
3178         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
3179         
3180         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3181                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3182
3183         if (fnum1 == -1) {
3184                 printf("test 3 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
3185                 CHECK_MAX_FAILURES(error_test30);
3186                 return False;
3187         }
3188
3189         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3190                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3191
3192         if (fnum2 == -1) {
3193                 printf("test 3 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
3194                 CHECK_MAX_FAILURES(error_test30);
3195                 return False;
3196         }
3197
3198         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
3199                 printf("test 3 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
3200                 return False;
3201         }
3202         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
3203                 printf("test 3 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
3204                 return False;
3205         }
3206
3207         printf("non-io open test #3 passed.\n");
3208 error_test30:
3209         smbcli_unlink(cli1->tree, fname);
3210
3211         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
3212         
3213         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3214                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3215
3216         if (fnum1 == -1) {
3217                 printf("test 4 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
3218                 CHECK_MAX_FAILURES(error_test40);
3219                 return False;
3220         }
3221
3222         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3223                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3224
3225         if (fnum2 != -1) {
3226                 printf("test 4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
3227                 CHECK_MAX_FAILURES(error_test40);
3228                 return False;
3229         }
3230
3231         printf("test 4 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
3232
3233         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
3234                 printf("test 4 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
3235                 return False;
3236         }
3237
3238         printf("non-io open test #4 passed.\n");
3239 error_test40:
3240         smbcli_unlink(cli1->tree, fname);
3241
3242         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
3243         
3244         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3245                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3246
3247         if (fnum1 == -1) {
3248                 printf("test 5 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
3249                 CHECK_MAX_FAILURES(error_test50);
3250                 return False;
3251         }
3252
3253         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3254                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3255
3256         if (fnum2 == -1) {
3257                 printf("test 5 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
3258                 CHECK_MAX_FAILURES(error_test50);
3259                 return False;
3260         }
3261
3262         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
3263                 printf("test 5 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
3264                 return False;
3265         }
3266
3267         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
3268                 printf("test 5 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
3269                 return False;
3270         }
3271
3272         printf("non-io open test #5 passed.\n");
3273 error_test50:
3274         printf("TEST #6 testing 1 non-io open, one io open\n");
3275         
3276         smbcli_unlink(cli1->tree, fname);
3277
3278         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
3279                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3280
3281         if (fnum1 == -1) {
3282                 printf("test 6 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
3283                 CHECK_MAX_FAILURES(error_test60);
3284                 return False;
3285         }
3286
3287         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3288                                    NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OPEN_IF, 0, 0);
3289
3290         if (fnum2 == -1) {
3291                 printf("test 6 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
3292                 CHECK_MAX_FAILURES(error_test60);
3293                 return False;
3294         }
3295
3296         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
3297                 printf("test 6 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
3298                 return False;
3299         }
3300
3301         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
3302                 printf("test 6 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
3303                 return False;
3304         }
3305
3306         printf("non-io open test #6 passed.\n");
3307 error_test60:
3308         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
3309
3310         smbcli_unlink(cli1->tree, fname);
3311
3312         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
3313                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3314
3315         if (fnum1 == -1) {
3316                 printf("test 7 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
3317                 CHECK_MAX_FAILURES(error_test70);
3318                 return False;
3319         }
3320
3321         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3322                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3323
3324         if (fnum2 != -1) {
3325                 printf("test 7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
3326                 CHECK_MAX_FAILURES(error_test70);
3327                 return False;
3328         }
3329
3330         printf("test 7 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
3331
3332         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
3333                 printf("test 7 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
3334                 return False;
3335         }
3336
3337         printf("non-io open test #7 passed.\n");
3338
3339 error_test70:
3340
3341         printf("TEST #8 testing one normal open, followed by lock, followed by open with truncate\n");
3342
3343         smbcli_unlink(cli1->tree, fname);
3344
3345         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
3346         if (fnum1 == -1) {
3347                 printf("(8) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
3348                 return False;
3349         }
3350         
3351         /* write 20 bytes. */
3352         
3353         memset(buf, '\0', 20);
3354
3355         if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
3356                 printf("(8) write failed (%s)\n", smbcli_errstr(cli1->tree));
3357                 correct = False;
3358         }
3359
3360         /* Ensure size == 20. */
3361         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
3362                 printf("(8) getatr (1) failed (%s)\n", smbcli_errstr(cli1->tree));
3363                 CHECK_MAX_FAILURES(error_test80);
3364                 return False;
3365         }
3366         
3367         if (fsize != 20) {
3368                 printf("(8) file size != 20\n");
3369                 CHECK_MAX_FAILURES(error_test80);
3370                 return False;
3371         }
3372
3373         /* Get an exclusive lock on the open file. */
3374         if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
3375                 printf("(8) lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
3376                 CHECK_MAX_FAILURES(error_test80);
3377                 return False;
3378         }
3379
3380         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
3381         if (fnum1 == -1) {
3382                 printf("(8) open (2) of %s with truncate failed (%s)\n", fname, smbcli_errstr(cli1->tree));
3383                 return False;
3384         }
3385
3386         /* Ensure size == 0. */
3387         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
3388                 printf("(8) getatr (2) failed (%s)\n", smbcli_errstr(cli1->tree));
3389                 CHECK_MAX_FAILURES(error_test80);
3390                 return False;
3391         }
3392         
3393         if (fsize != 0) {
3394                 printf("(8) file size != 0\n");
3395                 CHECK_MAX_FAILURES(error_test80);
3396                 return False;
3397         }
3398
3399         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
3400                 printf("(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
3401                 return False;
3402         }
3403         
3404         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
3405                 printf("(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
3406                 return False;
3407         }
3408         
3409 error_test80:
3410
3411         printf("open test #8 passed.\n");
3412
3413         smbcli_unlink(cli1->tree, fname);
3414
3415         if (!torture_close_connection(cli1)) {
3416                 correct = False;
3417         }
3418         if (!torture_close_connection(cli2)) {
3419                 correct = False;
3420         }
3421         
3422         return correct;
3423 }
3424
3425
3426 static uint32_t open_attrs_table[] = {
3427                 FILE_ATTRIBUTE_NORMAL,
3428                 FILE_ATTRIBUTE_ARCHIVE,
3429                 FILE_ATTRIBUTE_READONLY,
3430                 FILE_ATTRIBUTE_HIDDEN,
3431                 FILE_ATTRIBUTE_SYSTEM,
3432
3433                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
3434                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
3435                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
3436                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
3437                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
3438                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
3439
3440                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
3441                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
3442                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
3443                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
3444 };
3445
3446 struct trunc_open_results {
3447         uint_t num;
3448         uint32_t init_attr;
3449         uint32_t trunc_attr;
3450         uint32_t result_attr;
3451 };
3452
3453 static struct trunc_open_results attr_results[] = {
3454         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
3455         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
3456         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
3457         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
3458         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
3459         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
3460         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3461         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3462         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
3463         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3464         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3465         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
3466         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3467         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3468         { 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 },
3469         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3470         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3471         { 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 },
3472         { 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 },
3473         { 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 },
3474         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3475         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3476         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
3477         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3478         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3479         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
3480 };
3481
3482 static BOOL run_openattrtest(int dummy)
3483 {
3484         struct smbcli_state *cli1;
3485         const char *fname = "\\openattr.file";
3486         int fnum1;
3487         BOOL correct = True;
3488         uint16_t attr;
3489         uint_t i, j, k, l;
3490         int failures = 0;
3491
3492         printf("starting open attr test\n");
3493         
3494         if (!torture_open_connection(&cli1)) {
3495                 return False;
3496         }
3497         
3498         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
3499                 smbcli_setatr(cli1->tree, fname, 0, 0);
3500                 smbcli_unlink(cli1->tree, fname);
3501                 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_WRITE_DATA, open_attrs_table[i],
3502                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3503
3504                 if (fnum1 == -1) {
3505                         printf("open %d (1) of %s failed (%s)\n", i, fname, smbcli_errstr(cli1->tree));
3506                         return False;
3507                 }
3508
3509                 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
3510                         printf("close %d (1) of %s failed (%s)\n", i, fname, smbcli_errstr(cli1->tree));
3511                         return False;
3512                 }
3513
3514                 for (j = 0; j < ARRAY_SIZE(open_attrs_table); j++) {
3515                         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
3516                                                    SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA, 
3517                                                    open_attrs_table[j],
3518                                                    NTCREATEX_SHARE_ACCESS_NONE, 
3519                                                    NTCREATEX_DISP_OVERWRITE, 0, 0);
3520
3521                         if (fnum1 == -1) {
3522                                 for (l = 0; l < ARRAY_SIZE(attr_results); l++) {
3523                                         if (attr_results[l].num == k) {
3524                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
3525                                                                 k, open_attrs_table[i],
3526                                                                 open_attrs_table[j],
3527                                                                 fname, NT_STATUS_V(smbcli_nt_error(cli1->tree)), smbcli_errstr(cli1->tree));
3528                                                 correct = False;
3529                                                 CHECK_MAX_FAILURES(error_exit);
3530                                         }
3531                                 }
3532                                 if (NT_STATUS_V(smbcli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) {
3533                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
3534                                                         k, open_attrs_table[i], open_attrs_table[j],
3535                                                         smbcli_errstr(cli1->tree));
3536                                         correct = False;
3537                                         CHECK_MAX_FAILURES(error_exit);
3538                                 }
3539 #if 0
3540                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
3541 #endif
3542                                 k++;
3543                                 continue;
3544                         }
3545
3546                         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
3547                                 printf("close %d (2) of %s failed (%s)\n", j, fname, smbcli_errstr(cli1->tree));
3548                                 return False;
3549                         }
3550
3551                         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, &attr, NULL, NULL))) {
3552                                 printf("getatr(2) failed (%s)\n", smbcli_errstr(cli1->tree));
3553                                 return False;
3554                         }
3555
3556 #if 0
3557                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
3558                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
3559 #endif
3560
3561                         for (l = 0; l < ARRAY_SIZE(attr_results); l++) {
3562                                 if (attr_results[l].num == k) {
3563                                         if (attr != attr_results[l].result_attr ||
3564                                                         open_attrs_table[i] != attr_results[l].init_attr ||
3565                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
3566                                                 printf("[%d] getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
3567                                                         k, open_attrs_table[i],
3568                                                         open_attrs_table[j],
3569                                                         (uint_t)attr,
3570                                                         attr_results[l].result_attr);
3571                                                 correct = False;
3572                                                 CHECK_MAX_FAILURES(error_exit);
3573                                         }
3574                                         break;
3575                                 }
3576                         }
3577                         k++;
3578                 }
3579         }
3580 error_exit:
3581         smbcli_setatr(cli1->tree, fname, 0, 0);
3582         smbcli_unlink(cli1->tree, fname);
3583
3584         printf("open attr test %s.\n", correct ? "passed" : "failed");
3585
3586         if (!torture_close_connection(cli1)) {
3587                 correct = False;
3588         }
3589         return correct;
3590 }
3591
3592 static void list_fn(file_info *finfo, const char *name, void *state)
3593 {
3594         
3595 }
3596
3597 /*
3598   test directory listing speed
3599  */
3600 static BOOL run_dirtest(int dummy)
3601 {
3602         int i;
3603         struct smbcli_state *cli;
3604         int fnum;
3605         double t1;
3606         BOOL correct = True;
3607
3608         printf("starting directory test\n");
3609
3610         if (!torture_open_connection(&cli)) {
3611                 return False;
3612         }
3613
3614         printf("Creating %d random filenames\n", torture_numops);
3615
3616         srandom(0);
3617         for (i=0;i<torture_numops;i++) {
3618                 char *fname;
3619                 asprintf(&fname, "\\%x", (int)random());
3620                 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
3621                 if (fnum == -1) {
3622                         fprintf(stderr,"Failed to open %s\n", fname);
3623                         return False;
3624                 }
3625                 smbcli_close(cli->tree, fnum);
3626                 free(fname);
3627         }
3628
3629         t1 = end_timer();
3630
3631         printf("Matched %d\n", smbcli_list(cli->tree, "a*.*", 0, list_fn, NULL));
3632         printf("Matched %d\n", smbcli_list(cli->tree, "b*.*", 0, list_fn, NULL));
3633         printf("Matched %d\n", smbcli_list(cli->tree, "xyzabc", 0, list_fn, NULL));
3634
3635         printf("dirtest core %g seconds\n", end_timer() - t1);
3636
3637         srandom(0);
3638         for (i=0;i<torture_numops;i++) {
3639                 char *fname;
3640                 asprintf(&fname, "\\%x", (int)random());
3641                 smbcli_unlink(cli->tree, fname);
3642                 free(fname);
3643         }
3644
3645         if (!torture_close_connection(cli)) {
3646                 correct = False;
3647         }
3648
3649         printf("finished dirtest\n");
3650
3651         return correct;
3652 }
3653
3654 /*
3655   sees what IOCTLs are supported
3656  */
3657 BOOL torture_ioctl_test(int dummy)
3658 {
3659         struct smbcli_state *cli;
3660         uint16_t device, function;
3661         int fnum;
3662         const char *fname = "\\ioctl.dat";
3663         NTSTATUS status;
3664         union smb_ioctl parms;
3665         TALLOC_CTX *mem_ctx;
3666
3667         if (!torture_open_connection(&cli)) {
3668                 return False;
3669         }
3670
3671         mem_ctx = talloc_init("ioctl_test");
3672
3673         printf("starting ioctl test\n");
3674
3675         smbcli_unlink(cli->tree, fname);
3676
3677         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
3678         if (fnum == -1) {
3679                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
3680                 return False;
3681         }
3682
3683         parms.ioctl.level = RAW_IOCTL_IOCTL;
3684         parms.ioctl.in.fnum = fnum;
3685         parms.ioctl.in.request = IOCTL_QUERY_JOB_INFO;
3686         status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
3687         printf("ioctl job info: %s\n", smbcli_errstr(cli->tree));
3688
3689         for (device=0;device<0x100;device++) {
3690                 printf("testing device=0x%x\n", device);
3691                 for (function=0;function<0x100;function++) {
3692                         parms.ioctl.in.request = (device << 16) | function;
3693                         status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
3694
3695                         if (NT_STATUS_IS_OK(status)) {
3696                                 printf("ioctl device=0x%x function=0x%x OK : %d bytes\n", 
3697                                         device, function, parms.ioctl.out.blob.length);
3698                         }
3699                 }
3700         }
3701
3702         if (!torture_close_connection(cli)) {
3703                 return False;
3704         }
3705
3706         return True;
3707 }
3708
3709
3710 /*
3711   tries variants of chkpath
3712  */
3713 BOOL torture_chkpath_test(int dummy)
3714 {
3715         struct smbcli_state *cli;
3716         int fnum;
3717         BOOL ret;
3718
3719         if (!torture_open_connection(&cli)) {
3720                 return False;
3721         }
3722
3723         printf("starting chkpath test\n");
3724
3725         printf("Testing valid and invalid paths\n");
3726
3727         /* cleanup from an old run */
3728         smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
3729         smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
3730         smbcli_rmdir(cli->tree, "\\chkpath.dir");
3731
3732         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir"))) {
3733                 printf("mkdir1 failed : %s\n", smbcli_errstr(cli->tree));
3734                 return False;
3735         }
3736
3737         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir\\dir2"))) {
3738                 printf("mkdir2 failed : %s\n", smbcli_errstr(cli->tree));
3739                 return False;
3740         }
3741
3742         fnum = smbcli_open(cli->tree, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
3743         if (fnum == -1) {
3744                 printf("open1 failed (%s)\n", smbcli_errstr(cli->tree));
3745                 return False;
3746         }
3747         smbcli_close(cli->tree, fnum);
3748
3749         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir"))) {
3750                 printf("chkpath1 failed: %s\n", smbcli_errstr(cli->tree));
3751                 ret = False;
3752         }
3753
3754         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dir2"))) {
3755                 printf("chkpath2 failed: %s\n", smbcli_errstr(cli->tree));
3756                 ret = False;
3757         }
3758
3759         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\foo.txt"))) {
3760                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath, 
3761                                   NT_STATUS_NOT_A_DIRECTORY);
3762         } else {
3763                 printf("* chkpath on a file should fail\n");
3764                 ret = False;
3765         }
3766
3767         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\bar.txt"))) {
3768                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadfile, 
3769                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
3770         } else {
3771                 printf("* chkpath on a non existent file should fail\n");
3772                 ret = False;
3773         }
3774
3775         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dirxx\\bar.txt"))) {
3776                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath, 
3777                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
3778         } else {
3779                 printf("* chkpath on a non existent component should fail\n");
3780                 ret = False;
3781         }
3782
3783         smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
3784         smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
3785         smbcli_rmdir(cli->tree, "\\chkpath.dir");
3786
3787         if (!torture_close_connection(cli)) {
3788                 return False;
3789         }
3790
3791         return ret;
3792 }
3793
3794 static BOOL run_dirtest1(int dummy)
3795 {
3796         int i;
3797         struct smbcli_state *cli;
3798         int fnum, num_seen;
3799         BOOL correct = True;
3800
3801         printf("starting directory test\n");
3802
3803         if (!torture_open_connection(&cli)) {
3804                 return False;
3805         }
3806
3807         if (smbcli_deltree(cli->tree, "\\LISTDIR") == -1) {
3808                 fprintf(stderr,"Failed to deltree %s, error=%s\n", "\\LISTDIR", smbcli_errstr(cli->tree));
3809                 return False;
3810         }
3811         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\LISTDIR"))) {
3812                 fprintf(stderr,"Failed to mkdir %s, error=%s\n", "\\LISTDIR", smbcli_errstr(cli->tree));
3813                 return False;
3814         }
3815
3816         printf("Creating %d files\n", torture_entries);
3817
3818         /* Create torture_entries files and torture_entries directories. */
3819         for (i=0;i<torture_entries;i++) {
3820                 char *fname;
3821                 asprintf(&fname, "\\LISTDIR\\f%d", i);
3822                 fnum = smbcli_nt_create_full(cli->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
3823                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3824                 if (fnum == -1) {
3825                         fprintf(stderr,"Failed to open %s, error=%s\n", fname, smbcli_errstr(cli->tree));
3826                         return False;
3827                 }
3828                 free(fname);
3829                 smbcli_close(cli->tree, fnum);
3830         }
3831         for (i=0;i<torture_entries;i++) {
3832                 char *fname;
3833                 asprintf(&fname, "\\LISTDIR\\d%d", i);
3834                 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, fname))) {
3835                         fprintf(stderr,"Failed to open %s, error=%s\n", fname, smbcli_errstr(cli->tree));
3836                         return False;
3837                 }
3838                 free(fname);
3839         }
3840
3841         /* Now ensure that doing an old list sees both files and directories. */
3842         num_seen = smbcli_list_old(cli->tree, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, NULL);
3843         printf("num_seen = %d\n", num_seen );
3844         /* We should see (torture_entries) each of files & directories + . and .. */
3845         if (num_seen != (2*torture_entries)+2) {
3846                 correct = False;
3847                 fprintf(stderr,"entry count mismatch, should be %d, was %d\n",
3848                         (2*torture_entries)+2, num_seen);
3849         }
3850                 
3851
3852         /* Ensure if we have the "must have" bits we only see the
3853          * relevant entries.
3854          */
3855         num_seen = smbcli_list_old(cli->tree, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, NULL);
3856         printf("num_seen = %d\n", num_seen );
3857         if (num_seen != torture_entries+2) {
3858                 correct = False;
3859                 fprintf(stderr,"entry count mismatch, should be %d, was %d\n",
3860                         torture_entries+2, num_seen);
3861         }
3862
3863         num_seen = smbcli_list_old(cli->tree, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, NULL);
3864         printf("num_seen = %d\n", num_seen );
3865         if (num_seen != torture_entries) {
3866                 correct = False;
3867                 fprintf(stderr,"entry count mismatch, should be %d, was %d\n",
3868                         torture_entries, num_seen);
3869         }
3870
3871         /* Delete everything. */
3872         if (smbcli_deltree(cli->tree, "\\LISTDIR") == -1) {
3873                 fprintf(stderr,"Failed to deltree %s, error=%s\n", "\\LISTDIR", smbcli_errstr(cli->tree));
3874                 return False;
3875         }
3876
3877 #if 0
3878         printf("Matched %d\n", smbcli_list(cli->tree, "a*.*", 0, list_fn, NULL));
3879         printf("Matched %d\n", smbcli_list(cli->tree, "b*.*", 0, list_fn, NULL));
3880         printf("Matched %d\n", smbcli_list(cli->tree, "xyzabc", 0, list_fn, NULL));
3881 #endif
3882
3883         if (!torture_close_connection(cli)) {
3884                 correct = False;
3885         }
3886
3887         printf("finished dirtest1\n");
3888
3889         return correct;
3890 }
3891
3892
3893 /*
3894    simple test harness for playing with deny modes
3895  */
3896 static BOOL run_deny3test(int dummy)
3897 {
3898         struct smbcli_state *cli1, *cli2;
3899         int fnum1, fnum2;
3900         const char *fname;
3901
3902         printf("starting deny3 test\n");
3903
3904         printf("Testing simple deny modes\n");
3905         
3906         if (!torture_open_connection(&cli1)) {
3907                 return False;
3908         }
3909         if (!torture_open_connection(&cli2)) {
3910                 return False;
3911         }
3912
3913         fname = "\\deny_dos1.dat";
3914
3915         smbcli_unlink(cli1->tree, fname);
3916         fnum1 = smbcli_open(cli1->tree, fname, O_CREAT|O_TRUNC|O_WRONLY, DENY_DOS);
3917         fnum2 = smbcli_open(cli1->tree, fname, O_CREAT|O_TRUNC|O_WRONLY, DENY_DOS);
3918         if (fnum1 != -1) smbcli_close(cli1->tree, fnum1);
3919         if (fnum2 != -1) smbcli_close(cli1->tree, fnum2);
3920         smbcli_unlink(cli1->tree, fname);
3921         printf("fnum1=%d fnum2=%d\n", fnum1, fnum2);
3922
3923
3924         fname = "\\deny_dos2.dat";
3925
3926         smbcli_unlink(cli1->tree, fname);
3927         fnum1 = smbcli_open(cli1->tree, fname, O_CREAT|O_TRUNC|O_WRONLY, DENY_DOS);
3928         fnum2 = smbcli_open(cli2->tree, fname, O_CREAT|O_TRUNC|O_WRONLY, DENY_DOS);
3929         if (fnum1 != -1) smbcli_close(cli1->tree, fnum1);
3930         if (fnum2 != -1) smbcli_close(cli2->tree, fnum2);
3931         smbcli_unlink(cli1->tree, fname);
3932         printf("fnum1=%d fnum2=%d\n", fnum1, fnum2);
3933
3934
3935         torture_close_connection(cli1);
3936         torture_close_connection(cli2);
3937
3938         return True;
3939 }
3940
3941 /*
3942   parse a //server/share type UNC name
3943 */
3944 static BOOL parse_unc(const char *unc_name, char **hostname, char **sharename)
3945 {
3946         char *p;
3947
3948         if (strncmp(unc_name, "//", 2)) {
3949                 return False;
3950         }
3951
3952         *hostname = strdup(&unc_name[2]);
3953         p = strchr_m(&(*hostname)[2],'/');
3954         if (!p) {
3955                 return False;
3956         }
3957         *p = 0;
3958         *sharename = strdup(p+1);
3959
3960         return True;
3961 }
3962
3963
3964
3965 static void sigcont(void)
3966 {
3967 }
3968
3969 double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result)
3970 {
3971         int i, status;
3972         volatile pid_t *child_status;
3973         volatile BOOL *child_status_out;
3974         int synccount;
3975         int tries = 8;
3976         double start_time_limit = 10 + (torture_nprocs * 1.5);
3977         char **unc_list = NULL;
3978         const char *p;
3979         int num_unc_names = 0;
3980
3981         synccount = 0;
3982
3983         signal(SIGCONT, sigcont);
3984
3985         child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*torture_nprocs);
3986         if (!child_status) {
3987                 printf("Failed to setup shared memory\n");
3988                 return -1;
3989         }
3990
3991         child_status_out = (volatile BOOL *)shm_setup(sizeof(BOOL)*torture_nprocs);
3992         if (!child_status_out) {
3993                 printf("Failed to setup result status shared memory\n");
3994                 return -1;
3995         }
3996
3997         p = lp_parm_string(-1, "torture", "unclist");
3998         if (p) {
3999                 unc_list = file_lines_load(p, &num_unc_names);
4000                 if (!unc_list || num_unc_names <= 0) {
4001                         printf("Failed to load unc names list from %s\n", p);
4002                         exit(1);
4003                 }
4004         }
4005
4006         for (i = 0; i < torture_nprocs; i++) {
4007                 child_status[i] = 0;
4008                 child_status_out[i] = True;
4009         }
4010
4011         start_timer();
4012
4013         for (i=0;i<torture_nprocs;i++) {
4014                 procnum = i;
4015                 if (fork() == 0) {
4016                         char *myname;
4017                         char *hostname=NULL, *sharename;
4018
4019                         pid_t mypid = getpid();
4020                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
4021
4022                         asprintf(&myname, "CLIENT%d", i);
4023                         lp_set_cmdline("netbios name", myname);
4024                         free(myname);
4025
4026
4027                         if (unc_list) {
4028                                 if (!parse_unc(unc_list[i % num_unc_names],
4029                                                &hostname, &sharename)) {
4030                                         printf("Failed to parse UNC name %s\n",
4031                                                unc_list[i % num_unc_names]);
4032                                         exit(1);
4033                                 }
4034                         }
4035
4036                         while (1) {
4037                                 if (hostname) {
4038                                         if (torture_open_connection_share(&current_cli,
4039                                                                           hostname, 
4040                                                                           sharename)) {
4041                                                 break;
4042                                         }
4043                                 } else if (torture_open_connection(&current_cli)) {
4044                                                 break;
4045                                 }
4046                                 if (tries-- == 0) {
4047                                         printf("pid %d failed to start\n", (int)getpid());
4048                                         _exit(1);
4049                                 }
4050                                 msleep(100);    
4051                         }
4052
4053                         child_status[i] = getpid();
4054
4055                         pause();
4056
4057                         if (child_status[i]) {
4058                                 printf("Child %d failed to start!\n", i);
4059                                 child_status_out[i] = 1;
4060                                 _exit(1);
4061                         }
4062
4063                         child_status_out[i] = fn(current_cli, i);
4064                         _exit(0);
4065                 }
4066         }
4067
4068         do {
4069                 synccount = 0;
4070                 for (i=0;i<torture_nprocs;i++) {
4071                         if (child_status[i]) synccount++;
4072                 }
4073                 if (synccount == torture_nprocs) break;
4074                 msleep(100);
4075         } while (end_timer() < start_time_limit);
4076
4077         if (synccount != torture_nprocs) {
4078                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
4079                 *result = False;
4080                 return end_timer();
4081         }
4082
4083         printf("Starting %d clients\n", torture_nprocs);
4084
4085         /* start the client load */
4086         start_timer();
4087         for (i=0;i<torture_nprocs;i++) {
4088                 child_status[i] = 0;
4089         }
4090         kill(0, SIGCONT);
4091
4092         printf("%d clients started\n", torture_nprocs);
4093
4094         for (i=0;i<torture_nprocs;i++) {
4095                 int ret;
4096                 while ((ret=waitpid(0, &status, 0)) == -1 && errno == EINTR) /* noop */ ;
4097                 if (ret == -1 || WEXITSTATUS(status) != 0) {
4098                         *result = False;
4099                 }
4100         }
4101
4102         printf("\n");
4103         
4104         for (i=0;i<torture_nprocs;i++) {
4105                 if (!child_status_out[i]) {
4106                         *result = False;
4107                 }
4108         }
4109         return end_timer();
4110 }
4111
4112 #define FLAG_MULTIPROC 1
4113
4114 static struct {
4115         const char *name;
4116         BOOL (*fn)(int);
4117         uint_t flags;
4118 } torture_ops[] = {
4119         /* base tests */
4120         {"BASE-FDPASS", run_fdpasstest, 0},
4121         {"BASE-LOCK1",  run_locktest1,  0},
4122         {"BASE-LOCK2",  run_locktest2,  0},
4123         {"BASE-LOCK3",  run_locktest3,  0},
4124         {"BASE-LOCK4",  run_locktest4,  0},
4125         {"BASE-LOCK5",  run_locktest5,  0},
4126         {"BASE-LOCK6",  run_locktest6,  0},
4127         {"BASE-LOCK7",  run_locktest7,  0},
4128         {"BASE-UNLINK", run_unlinktest, 0},
4129         {"BASE-ATTR",   run_attrtest,   0},
4130         {"BASE-TRANS2", run_trans2test, 0},
4131         {"BASE-NEGNOWAIT", run_negprot_nowait, 0},
4132         {"BASE-DIR",  run_dirtest, 0},
4133         {"BASE-DIR1",  run_dirtest1, 0},
4134         {"BASE-DENY1",  torture_denytest1, 0},
4135         {"BASE-DENY2",  torture_denytest2, 0},
4136         {"BASE-TCON",  run_tcon_test, 0},
4137         {"BASE-TCONDEV",  run_tcon_devtype_test, 0},
4138         {"BASE-VUID", run_vuidtest, 0},
4139         {"BASE-RW1",  run_readwritetest, 0},
4140         {"BASE-RW2",  run_readwritemulti, FLAG_MULTIPROC},
4141         {"BASE-OPEN", run_opentest, 0},
4142         {"BASE-DENY3", run_deny3test, 0},
4143         {"BASE-DEFER_OPEN", run_deferopen, FLAG_MULTIPROC},
4144         {"BASE-XCOPY", run_xcopy, 0},
4145         {"BASE-RENAME", run_rename, 0},
4146         {"BASE-DELETE", run_deletetest, 0},
4147         {"BASE-PROPERTIES", run_properties, 0},
4148         {"BASE-MANGLE", torture_mangle, 0},
4149         {"BASE-OPENATTR", run_openattrtest, 0},
4150         {"BASE-CHARSET", torture_charset, 0},
4151         {"BASE-CHKPATH",  torture_chkpath_test, 0},
4152
4153         /* benchmarking tests */
4154         {"BENCH-HOLDCON",  torture_holdcon, 0},
4155         {"BENCH-NBENCH",  torture_nbench, 0},
4156         {"BENCH-TORTURE",run_torture,    FLAG_MULTIPROC},
4157
4158         /* RAW smb tests */
4159         {"RAW-QFSINFO", torture_raw_qfsinfo, 0},
4160         {"RAW-QFILEINFO", torture_raw_qfileinfo, 0},
4161         {"RAW-SFILEINFO", torture_raw_sfileinfo, 0},
4162         {"RAW-SFILEINFO-BUG", torture_raw_sfileinfo_bug, 0},
4163         {"RAW-SEARCH", torture_raw_search, 0},
4164         {"RAW-CLOSE", torture_raw_close, 0},
4165         {"RAW-OPEN", torture_raw_open, 0},
4166         {"RAW-MKDIR", torture_raw_mkdir, 0},
4167         {"RAW-OPLOCK", torture_raw_oplock, 0},
4168         {"RAW-NOTIFY", torture_raw_notify, 0},
4169         {"RAW-MUX", torture_raw_mux, 0},
4170         {"RAW-IOCTL", torture_raw_ioctl, 0},
4171         {"RAW-CHKPATH", torture_raw_chkpath, 0},
4172         {"RAW-UNLINK", torture_raw_unlink, 0},
4173         {"RAW-READ", torture_raw_read, 0},
4174         {"RAW-WRITE", torture_raw_write, 0},
4175         {"RAW-LOCK", torture_raw_lock, 0},
4176         {"RAW-CONTEXT", torture_raw_context, 0},
4177         {"RAW-RENAME", torture_raw_rename, 0},
4178         {"RAW-SEEK", torture_raw_seek, 0},
4179         {"RAW-RAP", torture_raw_rap, 0},
4180
4181         /* protocol scanners */
4182         {"SCAN-TRANS2", torture_trans2_scan, 0},
4183         {"SCAN-NTTRANS", torture_nttrans_scan, 0},
4184         {"SCAN-ALIASES", torture_trans2_aliases, 0},
4185         {"SCAN-SMB", torture_smb_scan, 0},
4186         {"SCAN-MAXFID", run_maxfidtest, FLAG_MULTIPROC},
4187         {"SCAN-UTABLE", torture_utable, 0},
4188         {"SCAN-CASETABLE", torture_casetable, 0},
4189         {"SCAN-PIPE_NUMBER", run_pipe_number, 0},
4190         {"SCAN-IOCTL",  torture_ioctl_test, 0},
4191
4192         /* rpc testers */
4193         {"RPC-LSA", torture_rpc_lsa, 0},
4194         {"RPC-ECHO", torture_rpc_echo, 0},
4195         {"RPC-DFS", torture_rpc_dfs, 0},
4196         {"RPC-SPOOLSS", torture_rpc_spoolss, 0},
4197         {"RPC-SAMR", torture_rpc_samr, 0},
4198         {"RPC-NETLOGON", torture_rpc_netlogon, 0},
4199         {"RPC-SCHANNEL", torture_rpc_schannel, 0},
4200         {"RPC-WKSSVC", torture_rpc_wkssvc, 0},
4201         {"RPC-SRVSVC", torture_rpc_srvsvc, 0},
4202         {"RPC-SVCCTL", torture_rpc_svcctl, 0},
4203         {"RPC-ATSVC", torture_rpc_atsvc, 0},
4204         {"RPC-EVENTLOG", torture_rpc_eventlog, 0},
4205         {"RPC-EPMAPPER", torture_rpc_epmapper, 0},
4206         {"RPC-WINREG", torture_rpc_winreg, 0},
4207         {"RPC-MGMT", torture_rpc_mgmt, 0},
4208         {"RPC-SCANNER", torture_rpc_scanner, 0},
4209         {"RPC-AUTOIDL", torture_rpc_autoidl, 0},
4210         {"RPC-MULTIBIND", torture_multi_bind, 0},
4211         {"RPC-DRSUAPI", torture_rpc_drsuapi, 0},
4212
4213         /* crypto testers */
4214         {"CRYPT-NTLMSSP", torture_ntlmssp_self_check, 0},
4215
4216         /* ldap testers */
4217         {"LDAP-BASIC", torture_ldap_basic, 0},
4218
4219         {NULL, NULL, 0}};
4220
4221
4222
4223 /****************************************************************************
4224 run a specified test or "ALL"
4225 ****************************************************************************/
4226 static BOOL run_test(const char *name)
4227 {
4228         BOOL ret = True;
4229         int i;
4230         BOOL matched = False;
4231
4232         if (strequal(name,"ALL")) {
4233                 for (i=0;torture_ops[i].name;i++) {
4234                         if (!run_test(torture_ops[i].name)) {
4235                                 ret = False;
4236                         }
4237                 }
4238                 return ret;
4239         }
4240
4241         for (i=0;torture_ops[i].name;i++) {
4242                 if (gen_fnmatch(name, torture_ops[i].name) == 0) {
4243                         double t;
4244                         matched = True;
4245                         printf("Running %s\n", torture_ops[i].name);
4246                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
4247                                 BOOL result;
4248                                 t = torture_create_procs(torture_ops[i].fn, &result);
4249                                 if (!result) { 
4250                                         ret = False;
4251                                         printf("TEST %s FAILED!\n", torture_ops[i].name);
4252                                 }
4253                                          
4254                         } else {
4255                                 start_timer();
4256                                 if (!torture_ops[i].fn(0)) {
4257                                         ret = False;
4258                                         printf("TEST %s FAILED!\n", torture_ops[i].name);
4259                                 }
4260                                 t = end_timer();
4261                         }
4262                         printf("%s took %g secs\n\n", torture_ops[i].name, t);
4263                 }
4264         }
4265
4266         if (!matched) {
4267                 printf("Unknown torture operation '%s'\n", name);
4268         }
4269
4270         return ret;
4271 }
4272
4273
4274 /*
4275   parse a username%password
4276 */
4277 static void parse_user(const char *user)
4278 {
4279         char *username, *password = NULL, *p;
4280
4281         username = strdup(user);
4282         p = strchr_m(username,'%');
4283         if (p) {
4284                 *p = 0;
4285                 password = strdup(p+1);
4286         }
4287
4288         lp_set_cmdline("torture:username", username);
4289
4290         if (password) {
4291                 lp_set_cmdline("torture:password", password);
4292         }
4293
4294         if (!lp_parm_string(-1,"torture","password")) {
4295                 password = getpass("password:");
4296
4297                 lp_set_cmdline("torture:password", password);
4298         }
4299 }
4300
4301 static void parse_dns(const char *dns)
4302 {
4303         char *userdn, *basedn, *secret;
4304         char *p, *d;
4305
4306         /* retrievieng the userdn */
4307         p = strchr_m(dns, '#');
4308         if (!p) {
4309                 lp_set_cmdline("torture:ldap_userdn", "");
4310                 lp_set_cmdline("torture:ldap_basedn", "");
4311                 lp_set_cmdline("torture:ldap_secret", "");
4312                 return;
4313         }
4314         userdn = strndup(dns, p - dns);
4315         lp_set_cmdline("torture:ldap_userdn", userdn);
4316
4317         /* retrieve the basedn */
4318         d = p + 1;
4319         p = strchr_m(d, '#');
4320         if (!p) {
4321                 lp_set_cmdline("torture:ldap_basedn", "");
4322                 lp_set_cmdline("torture:ldap_secret", "");
4323                 return;
4324         }
4325         basedn = strndup(d, p - d);
4326         lp_set_cmdline("torture:ldap_basedn", basedn);
4327
4328         /* retrieve the secret */
4329         p = p + 1;
4330         if (!p) {
4331                 lp_set_cmdline("torture:ldap_secret", "");
4332                 return;
4333         }
4334         secret = strdup(p);
4335         lp_set_cmdline("torture:ldap_secret", secret);
4336
4337         printf ("%s - %s - %s\n", userdn, basedn, secret);
4338
4339 }
4340
4341 static void usage(void)
4342 {
4343         int i;
4344
4345         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
4346
4347         printf("\t-d debuglevel\n");
4348         printf("\t-U user%%pass\n");
4349         printf("\t-k use kerberos\n");
4350         printf("\t-N numprocs\n");
4351         printf("\t-n my_netbios_name\n");
4352         printf("\t-W workgroup\n");
4353         printf("\t-o num_operations\n");
4354         printf("\t-e num files(entries)\n");
4355         printf("\t-O socket_options\n");
4356         printf("\t-m maximum protocol\n");
4357         printf("\t-L use oplocks\n");
4358         printf("\t-c CLIENT.TXT   specify client load file for NBENCH\n");
4359         printf("\t-t timelimit    specify NBENCH time limit (seconds)\n");
4360         printf("\t-C filename     specifies file with list of UNCs for connections\n");
4361         printf("\t-A showall\n");
4362         printf("\t-p port\n");
4363         printf("\t-s seed\n");
4364         printf("\t-f max failures\n");
4365         printf("\t-X enable dangerous tests\n");
4366         printf("\n\n");
4367
4368         printf("tests are:");
4369         for (i=0;torture_ops[i].name;i++) {
4370                 printf(" %s", torture_ops[i].name);
4371         }
4372         printf("\n");
4373
4374         printf("default test is ALL\n");
4375         
4376         exit(1);
4377 }
4378
4379 /****************************************************************************
4380   main program
4381 ****************************************************************************/
4382  int main(int argc,char *argv[])
4383 {
4384         int opt, i;
4385         char *p;
4386         BOOL correct = True;
4387         char *host, *share, *username;
4388
4389         setup_logging("smbtorture", DEBUG_STDOUT);
4390
4391 #ifdef HAVE_SETBUFFER
4392         setbuffer(stdout, NULL, 0);
4393 #endif
4394
4395         lp_load(dyn_CONFIGFILE,True,False,False);
4396         load_interfaces();
4397
4398         if (argc < 2) {
4399                 usage();
4400         }
4401
4402         for(p = argv[1]; *p; p++)
4403           if(*p == '\\')
4404             *p = '/';
4405
4406
4407         /* see if its a RPC transport specifier */
4408         if (strncmp(argv[1], "ncacn_", 6) == 0) {
4409                 lp_set_cmdline("torture:binding", argv[1]);
4410         } else {
4411                 char *binding = NULL;
4412
4413                 if (!parse_unc(argv[1], &host, &share)) {
4414                         usage();
4415                 }
4416
4417                 lp_set_cmdline("torture:host", host);
4418                 lp_set_cmdline("torture:share", share);
4419                 asprintf(&binding, "ncacn_np:%s", host);
4420                 lp_set_cmdline("torture:binding", binding);
4421         }
4422
4423         if (getenv("LOGNAME")) {
4424                 username = strdup(getenv("LOGNAME"));
4425         }
4426         lp_set_cmdline("torture:username", username);
4427
4428
4429         argc--;
4430         argv++;
4431
4432         srandom(time(NULL));
4433
4434         while ((opt = getopt(argc, argv, "p:hW:D:U:n:N:O:o:e:m:Ld:Ac:ks:f:s:t:C:X")) != EOF) {
4435                 switch (opt) {
4436                 case 'p':
4437                         lp_set_cmdline("smb ports", optarg);
4438                         break;
4439                 case 'W':
4440                         lp_set_cmdline("workgroup", optarg);
4441                         break;
4442                 case 'm':
4443                         lp_set_cmdline("protocol", optarg);
4444                         break;
4445                 case 'n':
4446                         lp_set_cmdline("netbios name", optarg);
4447                         break;
4448                 case 'd':
4449                         lp_set_cmdline("debug level", optarg);
4450                         setup_logging(NULL, DEBUG_STDOUT);
4451                         break;
4452                 case 'O':
4453                         lp_set_cmdline("socket options", optarg);
4454                         break;
4455                 case 's':
4456                         srandom(atoi(optarg));
4457                         break;
4458                 case 'N':
4459                         torture_nprocs = atoi(optarg);
4460                         break;
4461                 case 'o':
4462                         torture_numops = atoi(optarg);
4463                         break;
4464                 case 'e':
4465                         torture_entries = atoi(optarg);
4466                         break;
4467                 case 'L':
4468                         use_oplocks = True;
4469                         break;
4470                 case 'A':
4471                         torture_showall = True;
4472                         break;
4473                 case 'c':
4474                         lp_set_cmdline("torture:loadfile", optarg);
4475                         break;
4476                 case 'C':
4477                         lp_set_cmdline("torture:unclist", optarg);
4478                         break;
4479                 case 't':
4480                         lp_set_cmdline("torture:timelimit", optarg);
4481                         break;
4482                 case 'k':
4483 #ifdef HAVE_KRB5
4484                         use_kerberos = True;
4485 #else
4486                         d_printf("No kerberos support compiled in\n");
4487                         exit(1);
4488 #endif
4489                         break;
4490                 case 'U':
4491                         parse_user(optarg);
4492                         break;
4493                 case 'D':
4494                         parse_dns(optarg);
4495                         break;
4496                 case 'f':
4497                         torture_failures = atoi(optarg);
4498                         break;
4499
4500                 case 'X':
4501                         lp_set_cmdline("torture:dangerous", "1");
4502                         break;
4503
4504                 default:
4505                         printf("Unknown option %c (%d)\n", (char)opt, opt);
4506                         usage();
4507                 }
4508         }
4509
4510         if (!lp_parm_string(-1,"torture","password")) {
4511                 lp_set_cmdline("torture:password", "");
4512         }
4513
4514         if (argc == optind) {
4515                 printf("You must specify a test to run, or 'ALL'\n");
4516         } else {
4517                 for (i=optind;i<argc;i++) {
4518                         if (!run_test(argv[i])) {
4519                                 correct = False;
4520                         }
4521                 }
4522         }
4523
4524         if (correct) {
4525                 return(0);
4526         } else {
4527                 return(1);
4528         }
4529 }