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