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