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