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