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