r1481: add idl file and torture test dummies
[samba.git] / source / 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 cli_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 cli_state *open_nbt_connection(void)
38 {
39         struct nmb_name called, calling;
40         struct in_addr ip;
41         struct cli_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 = cli_state_init();
50         if (!cli) {
51                 printf("Failed initialize cli_struct to connect with %s\n", host);
52                 return NULL;
53         }
54
55         if (!cli_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 (!cli_transport_establish(cli, &calling, &called)) {
63                 /*
64                  * Well, that failed, try *SMBSERVER ... 
65                  * However, we must reconnect as well ...
66                  */
67                 if (!cli_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 (!cli_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                         cli_shutdown(cli);
78                         return NULL;
79                 }
80         }
81
82         return cli;
83 }
84
85 BOOL torture_open_connection_share(struct cli_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 |= CLI_FULL_CONNECTION_USE_KERBEROS;
97
98         status = cli_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 cli_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 cli_state *c)
126 {
127         BOOL ret = True;
128         DEBUG(9,("torture_close_connection: cli_state@%p\n", c));
129         if (!c) return True;
130         if (NT_STATUS_IS_ERR(cli_tdis(c))) {
131                 printf("tdis failed (%s)\n", cli_errstr(c->tree));
132                 ret = False;
133         }
134         DEBUG(9,("torture_close_connection: call cli_shutdown\n"));
135         cli_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 cli_state *c, 
173                         uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
174 {
175         if (cli_is_dos_error(c->tree)) {
176                 uint8_t class;
177                 uint32_t num;
178
179                 /* Check DOS error */
180
181                 cli_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 = cli_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 cli_state *c, int fnum, uint32_t offset, uint32_t len)
210 {
211         while (NT_STATUS_IS_ERR(cli_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 cli_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 = cli_open(c->tree, lockfname, O_RDWR | O_CREAT | O_EXCL, 
230                          DENY_NONE);
231         if (fnum2 == -1)
232                 fnum2 = cli_open(c->tree, lockfname, O_RDWR, DENY_NONE);
233         if (fnum2 == -1) {
234                 printf("open of %s failed (%s)\n", lockfname, cli_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 = cli_open(c->tree, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
251                 if (fnum == -1) {
252                         printf("open failed (%s)\n", cli_errstr(c->tree));
253                         correct = False;
254                         break;
255                 }
256
257                 if (cli_write(c->tree, fnum, 0, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
258                         printf("write failed (%s)\n", cli_errstr(c->tree));
259                         correct = False;
260                 }
261
262                 for (j=0;j<50;j++) {
263                         if (cli_write(c->tree, fnum, 0, (char *)buf, 
264                                       sizeof(pid)+(j*sizeof(buf)), 
265                                       sizeof(buf)) != sizeof(buf)) {
266                                 printf("write failed (%s)\n", cli_errstr(c->tree));
267                                 correct = False;
268                         }
269                 }
270
271                 pid2 = 0;
272
273                 if (cli_read(c->tree, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
274                         printf("read failed (%s)\n", cli_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(cli_close(c->tree, fnum))) {
284                         printf("close failed (%s)\n", cli_errstr(c->tree));
285                         correct = False;
286                 }
287
288                 if (NT_STATUS_IS_ERR(cli_unlink(c->tree, fname))) {
289                         printf("unlink failed (%s)\n", cli_errstr(c->tree));
290                         correct = False;
291                 }
292
293                 if (NT_STATUS_IS_ERR(cli_unlock(c->tree, fnum2, n*sizeof(int), sizeof(int)))) {
294                         printf("unlock failed (%s)\n", cli_errstr(c->tree));
295                         correct = False;
296                 }
297                 free(fname);
298         }
299
300         cli_close(c->tree, fnum2);
301         cli_unlink(c->tree, lockfname);
302
303         printf("%d\n", i);
304
305         return correct;
306 }
307
308 static BOOL run_torture(struct cli_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 cli_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 = cli_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, cli_errstr(c->tree));
345                         return False;
346                 }
347         }
348         else
349         {
350                 for (i = 0; i < 500 && fnum == -1; i++)
351                 {
352                         fnum = cli_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, cli_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 (cli_write(c->tree, fnum, 0, buf+count, count, (size_t)sent) != sent) {
382                                 printf("write failed (%s)\n", cli_errstr(c->tree));
383                                 correct = False;
384                         }
385                 }
386                 else
387                 {
388                         sent = cli_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                                                 cli_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(cli_close(c->tree, fnum))) {
414                 printf("close failed (%s)\n", cli_errstr(c->tree));
415                 correct = False;
416         }
417
418         return correct;
419 }
420
421 static BOOL rw_torture2(struct cli_state *c1, struct cli_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 (cli_deltree(c1->tree, lockfname) == -1) {
433                 printf("unlink failed (%s)\n", cli_errstr(c1->tree));
434         }
435
436         fnum1 = cli_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, cli_errstr(c1->tree));
441                 return False;
442         }
443         fnum2 = cli_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, cli_errstr(c2->tree));
448                 cli_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, False);
462
463                 if ((bytes_written = cli_write(c1->tree, fnum1, 0, buf, 0, buf_size)) != buf_size) {
464                         printf("write failed (%s)\n", cli_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 = cli_read(c2->tree, fnum2, buf_rd, 0, buf_size)) != buf_size) {
471                         printf("read failed (%s)\n", cli_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(cli_close(c2->tree, fnum2))) {
486                 printf("close failed (%s)\n", cli_errstr(c2->tree));
487                 correct = False;
488         }
489         if (NT_STATUS_IS_ERR(cli_close(c1->tree, fnum1))) {
490                 printf("close failed (%s)\n", cli_errstr(c1->tree));
491                 correct = False;
492         }
493
494         if (NT_STATUS_IS_ERR(cli_unlink(c1->tree, lockfname))) {
495                 printf("unlink failed (%s)\n", cli_errstr(c1->tree));
496                 correct = False;
497         }
498
499         return correct;
500 }
501
502 static BOOL run_readwritetest(int dummy)
503 {
504         struct cli_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 cli_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 cli_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         cli_unlink(cli1->tree, fname);
568
569         fnum1 = cli_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, cli_errstr(cli1->tree));
572                 return False;
573         }
574         fnum2 = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
575         if (fnum2 == -1) {
576                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
577                 return False;
578         }
579         fnum3 = cli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
580         if (fnum3 == -1) {
581                 printf("open3 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
582                 return False;
583         }
584
585         if (NT_STATUS_IS_ERR(cli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
586                 printf("lock1 failed (%s)\n", cli_errstr(cli1->tree));
587                 return False;
588         }
589
590
591         if (NT_STATUS_IS_OK(cli_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(cli_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(cli_close(cli1->tree, fnum2))) {
619                 printf("close1 failed (%s)\n", cli_errstr(cli1->tree));
620                 return False;
621         }
622
623         if (NT_STATUS_IS_OK(cli_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(cli_close(cli1->tree, fnum1))) {
632                 printf("close2 failed (%s)\n", cli_errstr(cli1->tree));
633                 return False;
634         }
635
636         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum3))) {
637                 printf("close3 failed (%s)\n", cli_errstr(cli2->tree));
638                 return False;
639         }
640
641         if (NT_STATUS_IS_ERR(cli_unlink(cli1->tree, fname))) {
642                 printf("unlink failed (%s)\n", cli_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 cli_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 cli_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 (cli_deltree(cli->tree, fname) == -1) {
684                 printf("unlink of %s failed (%s)\n", fname, cli_errstr(cli->tree));
685         }
686
687         fnum1 = cli_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, cli_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 (cli_write(cli->tree, fnum1, 0, buf, 130, 4) != 4) {
698                 printf("initial write failed (%s)\n", cli_errstr(cli->tree));
699                 return False;
700         }
701
702         tree1 = cli->tree;      /* save old tree connection */
703         if (NT_STATUS_IS_ERR(cli_send_tconX(cli, share, "?????", password))) {
704                 printf("%s refused 2nd tree connect (%s)\n", host,
705                            cli_errstr(cli->tree));
706                 cli_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 (cli_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", cli_errstr(cli->tree));
722         }
723
724
725         /* try a write with an invalid tid */
726         cli->tree->tid = cnum3;
727
728         if (cli_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", cli_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 (cli_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", cli_errstr(cli->tree));
744         }
745
746         cli->session->vuid = vuid1;
747         cli->tree->tid = cnum1;
748
749         if (NT_STATUS_IS_ERR(cli_close(cli->tree, fnum1))) {
750                 printf("close failed (%s)\n", cli_errstr(cli->tree));
751                 return False;
752         }
753
754         cli->tree->tid = cnum2;
755
756         if (NT_STATUS_IS_ERR(cli_tdis(cli))) {
757                 printf("secondary tdis failed (%s)\n", cli_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 cli_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(cli_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                 cli_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(cli_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 cli_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 = cli_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         cli_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 cli_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         cli_unlink(cli->tree, fname);
905
906         printf("Testing pid context\n");
907         
908         cli->session->pid = 1;
909
910         fnum1 = cli_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, cli_errstr(cli->tree));
913                 return False;
914         }
915
916         fnum2 = cli_open(cli->tree, fname, O_RDWR, DENY_NONE);
917         if (fnum2 == -1) {
918                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(cli->tree));
919                 return False;
920         }
921
922         cli->session->pid = 2;
923
924         fnum3 = cli_open(cli->tree, fname, O_RDWR, DENY_NONE);
925         if (fnum3 == -1) {
926                 printf("open3 of %s failed (%s)\n", fname, cli_errstr(cli->tree));
927                 return False;
928         }
929
930         cli->session->pid = 1;
931
932         if (NT_STATUS_IS_ERR(cli_lock(cli->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
933                 printf("lock1 failed (%s)\n", cli_errstr(cli->tree));
934                 return False;
935         }
936
937         if (NT_STATUS_IS_OK(cli_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(cli_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(cli_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(cli_lock(cli->tree, fnum1, 100, 4, 0, WRITE_LOCK))) {
962                 printf("lock at 100 failed (%s)\n", cli_errstr(cli->tree));
963         }
964
965         cli->session->pid = 2;
966
967         if (NT_STATUS_IS_OK(cli_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(cli_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(cli_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(cli_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(cli_close(cli->tree, fnum1))) {
1000                 printf("close1 failed (%s)\n", cli_errstr(cli->tree));
1001                 return False;
1002         }
1003
1004         if (NT_STATUS_IS_ERR(cli_close(cli->tree, fnum2))) {
1005                 printf("close2 failed (%s)\n", cli_errstr(cli->tree));
1006                 return False;
1007         }
1008
1009         if (NT_STATUS_IS_ERR(cli_close(cli->tree, fnum3))) {
1010                 printf("close3 failed (%s)\n", cli_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 cli_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         cli_unlink(cli1->tree, fname);
1048
1049         fnum1 = cli_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, cli_errstr(cli1->tree));
1052                 return False;
1053         }
1054         fnum2 = cli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
1055         if (fnum2 == -1) {
1056                 printf("open2 of %s failed (%s)\n", fname, cli_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(cli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK))) {
1065                         printf("lock1 %d failed (%s)\n", 
1066                                i,
1067                                cli_errstr(cli1->tree));
1068                         return False;
1069                 }
1070
1071                 if (NT_STATUS_IS_ERR(cli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK))) {
1072                         printf("lock2 %d failed (%s)\n", 
1073                                i,
1074                                cli_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(cli_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(cli_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(cli_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(cli_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(cli_unlock(cli1->tree, fnum1, offset-1, 1))) {
1111                         printf("unlock1 %d failed (%s)\n", 
1112                                i,
1113                                cli_errstr(cli1->tree));
1114                         return False;
1115                 }
1116
1117                 if (NT_STATUS_IS_ERR(cli_unlock(cli2->tree, fnum2, offset-2, 1))) {
1118                         printf("unlock2 %d failed (%s)\n", 
1119                                i,
1120                                cli_errstr(cli1->tree));
1121                         return False;
1122                 }
1123         }
1124
1125         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
1126                 printf("close1 failed (%s)\n", cli_errstr(cli1->tree));
1127                 return False;
1128         }
1129
1130         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum2))) {
1131                 printf("close2 failed (%s)\n", cli_errstr(cli2->tree));
1132                 return False;
1133         }
1134
1135         if (NT_STATUS_IS_ERR(cli_unlink(cli1->tree, fname))) {
1136                 printf("unlink failed (%s)\n", cli_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 cli_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         cli_unlink(cli1->tree, fname);
1176
1177         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1178         fnum2 = cli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
1179
1180         memset(buf, 0, sizeof(buf));
1181
1182         if (cli_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(cli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1189               NT_STATUS_IS_OK(cli_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(cli_lock(cli1->tree, fnum1, 10, 4, 0, READ_LOCK)) &&
1194               NT_STATUS_IS_OK(cli_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(cli_lock(cli1->tree, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1199               NT_STATUS_IS_OK(cli_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(cli_lock(cli1->tree, fnum1, 30, 4, 0, READ_LOCK)) &&
1204                 NT_STATUS_IS_OK(cli_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, cli_lock(cli1->tree, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1209               NT_STATUS_IS_OK((cli1->session->pid = 2, cli_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, cli_lock(cli1->tree, fnum1, 50, 4, 0, READ_LOCK))) &&
1214               NT_STATUS_IS_OK((cli1->session->pid = 2, cli_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(cli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK)) &&
1219               NT_STATUS_IS_OK(cli_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(cli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1224               NT_STATUS_IS_OK(cli_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(cli_lock(cli1->tree, fnum1, 80, 4, 0, READ_LOCK)) &&
1229               NT_STATUS_IS_OK(cli_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(cli_lock(cli1->tree, fnum1, 90, 4, 0, WRITE_LOCK)) &&
1234               NT_STATUS_IS_OK(cli_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, cli_lock(cli1->tree, fnum1, 100, 4, 0, WRITE_LOCK))) &&
1239               NT_STATUS_IS_OK((cli1->session->pid = 2, cli_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(cli_lock(cli1->tree, fnum1, 110, 4, 0, READ_LOCK)) &&
1244               NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 112, 4, 0, READ_LOCK)) &&
1245               NT_STATUS_IS_OK(cli_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(cli_lock(cli1->tree, fnum1, 120, 4, 0, WRITE_LOCK)) &&
1251               (cli_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(cli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK)) &&
1256               (cli_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(cli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) &&
1262               NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) &&
1263               NT_STATUS_IS_OK(cli_unlock(cli1->tree, fnum1, 140, 4)) &&
1264               NT_STATUS_IS_OK(cli_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(cli_lock(cli1->tree, fnum1, 150, 4, 0, WRITE_LOCK)) &&
1270               NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 150, 4, 0, READ_LOCK)) &&
1271               NT_STATUS_IS_OK(cli_unlock(cli1->tree, fnum1, 150, 4)) &&
1272               (cli_read(cli2->tree, fnum2, buf, 150, 4) == 4) &&
1273               !(cli_write(cli2->tree, fnum2, 0, buf, 150, 4) == 4) &&
1274               NT_STATUS_IS_OK(cli_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(cli_lock(cli1->tree, fnum1, 160, 4, 0, READ_LOCK)) &&
1279               NT_STATUS_IS_OK(cli_unlock(cli1->tree, fnum1, 160, 4)) &&
1280               (cli_write(cli2->tree, fnum2, 0, buf, 160, 4) == 4) &&            
1281               (cli_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(cli_lock(cli1->tree, fnum1, 170, 4, 0, WRITE_LOCK)) &&
1286               NT_STATUS_IS_OK(cli_unlock(cli1->tree, fnum1, 170, 4)) &&
1287               (cli_write(cli2->tree, fnum2, 0, buf, 170, 4) == 4) &&            
1288               (cli_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(cli_lock(cli1->tree, fnum1, 190, 4, 0, WRITE_LOCK)) &&
1293               NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 190, 4, 0, READ_LOCK)) &&
1294               NT_STATUS_IS_OK(cli_unlock(cli1->tree, fnum1, 190, 4)) &&
1295               !(cli_write(cli2->tree, fnum2, 0, buf, 190, 4) == 4) &&           
1296               (cli_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         cli_close(cli1->tree, fnum1);
1301         cli_close(cli2->tree, fnum2);
1302         fnum1 = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1303         f = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1304         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) &&
1305               NT_STATUS_IS_OK(cli_lock(cli1->tree, f, 0, 1, 0, READ_LOCK)) &&
1306               NT_STATUS_IS_OK(cli_close(cli1->tree, fnum1)) &&
1307               ((fnum1 = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE)) != -1) &&
1308               NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK));
1309         cli_close(cli1->tree, f);
1310         cli_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         cli_close(cli1->tree, fnum1);
1316         cli_close(cli2->tree, fnum2);
1317         cli_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 cli_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         cli_unlink(cli1->tree, fname);
1344
1345         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1346         fnum2 = cli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
1347         fnum3 = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1348
1349         memset(buf, 0, sizeof(buf));
1350
1351         if (cli_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(cli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) &&
1359                   NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum3, 0, 1, 0, READ_LOCK));
1360         cli_close(cli1->tree, fnum1);
1361         fnum1 = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1362         ret = NT_STATUS_IS_OK(cli_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         cli_close(cli1->tree, fnum1);
1366         fnum1 = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1367         cli_unlock(cli1->tree, fnum3, 0, 1);
1368
1369         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1370               NT_STATUS_IS_OK(cli_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(cli_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         cli_unlock(cli2->tree, fnum2, 0, 4);
1381
1382         ret = NT_STATUS_IS_OK(cli_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         cli_unlock(cli1->tree, fnum3, 0, 4);
1389
1390         /* Stack 2 more locks here. */
1391         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK)) &&
1392                   NT_STATUS_IS_OK(cli_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(cli_unlock(cli1->tree, fnum1, 0, 4)) &&
1401         NT_STATUS_IS_OK(cli_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         cli_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(cli_unlock(cli1->tree, fnum1, 1, 1)) &&
1412                   NT_STATUS_IS_OK(cli_unlock(cli1->tree, fnum1, 0, 4)) &&
1413                   NT_STATUS_IS_OK(cli_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(cli_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(cli_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         cli_close(cli1->tree, fnum1);
1432         cli_close(cli2->tree, fnum2);
1433         cli_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 cli_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                 cli_unlink(cli->tree, fname[i]);
1467
1468                 fnum = cli_open(cli->tree, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1469                 status = cli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
1470                 cli_close(cli->tree, fnum);
1471                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
1472
1473                 fnum = cli_open(cli->tree, fname[i], O_RDWR, DENY_NONE);
1474                 status = cli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
1475                 cli_close(cli->tree, fnum);
1476                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
1477
1478                 cli_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 cli_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         cli_unlink(cli1->tree, fname);
1504
1505         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1506
1507         memset(buf, 0, sizeof(buf));
1508
1509         if (cli_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(cli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK))) {
1517                 printf("Unable to apply read lock on range 130:4, error was %s\n", cli_errstr(cli1->tree));
1518                 goto fail;
1519         } else {
1520                 printf("pid1 successfully locked range 130:4 for READ\n");
1521         }
1522
1523         if (cli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
1524                 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1525                 goto fail;
1526         } else {
1527                 printf("pid1 successfully read the range 130:4\n");
1528         }
1529
1530         if (cli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
1531                 printf("pid1 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1532                 if (NT_STATUS_V(cli_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 (cli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
1544                 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1545         } else {
1546                 printf("pid2 successfully read the range 130:4\n");
1547         }
1548
1549         if (cli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
1550                 printf("pid2 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1551                 if (NT_STATUS_V(cli_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         cli_unlock(cli1->tree, fnum1, 130, 4);
1562
1563         if (NT_STATUS_IS_ERR(cli_lock(cli1->tree, fnum1, 130, 4, 0, WRITE_LOCK))) {
1564                 printf("Unable to apply write lock on range 130:4, error was %s\n", cli_errstr(cli1->tree));
1565                 goto fail;
1566         } else {
1567                 printf("pid1 successfully locked range 130:4 for WRITE\n");
1568         }
1569
1570         if (cli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
1571                 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1572                 goto fail;
1573         } else {
1574                 printf("pid1 successfully read the range 130:4\n");
1575         }
1576
1577         if (cli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
1578                 printf("pid1 unable to write to the range 130:4, error was %s\n", cli_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 (cli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
1587                 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1588                 if (NT_STATUS_V(cli_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 (cli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
1598                 printf("pid2 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1599                 if (NT_STATUS_V(cli_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 = cli_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(cli_getatr(cli1->tree, fname, NULL, &size, NULL))) {
1621                 printf("getatr failed (%s)\n", cli_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         cli_unlock(cli1->tree, fnum1, 130, 4);
1635         correct = True;
1636
1637 fail:
1638         cli_close(cli1->tree, fnum1);
1639         cli_close(cli1->tree, fnum2);
1640         cli_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 cli_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         cli_unlink(cli1->tree, fname);
1665
1666         printf("Opening a file on connection 1\n");
1667
1668         fnum1 = cli_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, cli_errstr(cli1->tree));
1671                 return False;
1672         }
1673
1674         printf("writing to file on connection 1\n");
1675
1676         if (cli_write(cli1->tree, fnum1, 0, "hello world\n", 0, 13) != 13) {
1677                 printf("write failed (%s)\n", cli_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 (cli_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         cli_close(cli1->tree, fnum1);
1695         cli_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 cli_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         cli_unlink(cli->tree, fname);
1726
1727         cli->session->pid = 1;
1728
1729         printf("Opening a file\n");
1730
1731         fnum = cli_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, cli_errstr(cli->tree));
1734                 return False;
1735         }
1736
1737         printf("Unlinking a open file\n");
1738
1739         if (NT_STATUS_IS_OK(cli_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         cli_close(cli->tree, fnum);
1748         cli_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 how many open files this server supports on the one socket
1762 */
1763
1764 static BOOL run_deferopen(struct cli_state *cli, int dummy)
1765 {
1766         const char *fname = "\\defer_open_test.dat";
1767         int retries=4;
1768         int i = 0;
1769         BOOL correct = True;
1770
1771         if (retries <= 0) {
1772                 printf("failed to connect\n");
1773                 return False;
1774         }
1775
1776         printf("Testing deferred open requests.\n");
1777
1778         while (i < 4) {
1779                 int fnum = -1;
1780
1781                 do {
1782                         struct timeval tv_start, tv_end;
1783                         GetTimeOfDay(&tv_start);
1784                         fnum = cli_nt_create_full(cli->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS,
1785                                 FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE,
1786                                 NTCREATEX_DISP_OPEN_IF, 0, 0);
1787                         if (fnum != -1) {
1788                                 break;
1789                         }
1790                         GetTimeOfDay(&tv_end);
1791                         if (NT_STATUS_EQUAL(cli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION)) {
1792                                 /* Sharing violation errors need to be 1 second apart. */
1793                                 int64_t tdif = usec_time_diff(&tv_end, &tv_start);
1794                                 if (tdif < 500000 || tdif > 1500000) {
1795                                         fprintf(stderr,"Timing incorrect %lld.%lld for share violation\n",
1796                                                 tdif / (int64_t)1000000, 
1797                                                 tdif % (int64_t)1000000);
1798                                 }
1799                         }
1800                 } while (NT_STATUS_EQUAL(cli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION));
1801
1802                 if (fnum == -1) {
1803                         fprintf(stderr,"Failed to open %s, error=%s\n", fname, cli_errstr(cli->tree));
1804                         return False;
1805                 }
1806
1807                 printf("pid %u open %d\n", getpid(), i);
1808
1809                 sleep(10);
1810                 i++;
1811                 if (NT_STATUS_IS_ERR(cli_close(cli->tree, fnum))) {
1812                         fprintf(stderr,"Failed to close %s, error=%s\n", fname, cli_errstr(cli->tree));
1813                         return False;
1814                 }
1815                 sleep(2);
1816         }
1817
1818         if (NT_STATUS_IS_ERR(cli_unlink(cli->tree, fname))) {
1819                 /* All until the last unlink will fail with sharing violation. */
1820                 if (!NT_STATUS_EQUAL(cli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION)) {
1821                         printf("unlink of %s failed (%s)\n", fname, cli_errstr(cli->tree));
1822                         correct = False;
1823                 }
1824         }
1825
1826         printf("deferred test finished\n");
1827         if (!torture_close_connection(cli)) {
1828                 correct = False;
1829         }
1830         return correct;
1831 }
1832
1833 /*
1834 test how many open files this server supports on the one socket
1835 */
1836 static BOOL run_maxfidtest(struct cli_state *cli, int dummy)
1837 {
1838         const char *template = "\\maxfid.%d.%d";
1839         char *fname;
1840         int fnums[0x11000], i;
1841         int retries=4;
1842         BOOL correct = True;
1843
1844         if (retries <= 0) {
1845                 printf("failed to connect\n");
1846                 return False;
1847         }
1848
1849         printf("Testing maximum number of open files\n");
1850
1851         for (i=0; i<0x11000; i++) {
1852                 asprintf(&fname, template, i,(int)getpid());
1853                 if ((fnums[i] = cli_open(cli->tree, fname, 
1854                                         O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) ==
1855                     -1) {
1856                         printf("open of %s failed (%s)\n", 
1857                                fname, cli_errstr(cli->tree));
1858                         printf("maximum fnum is %d\n", i);
1859                         break;
1860                 }
1861                 free(fname);
1862                 printf("%6d\r", i);
1863         }
1864         printf("%6d\n", i);
1865         i--;
1866
1867         printf("cleaning up\n");
1868         for (;i>=0;i--) {
1869                 asprintf(&fname, template, i,(int)getpid());
1870                 if (NT_STATUS_IS_ERR(cli_close(cli->tree, fnums[i]))) {
1871                         printf("Close of fnum %d failed - %s\n", fnums[i], cli_errstr(cli->tree));
1872                 }
1873                 if (NT_STATUS_IS_ERR(cli_unlink(cli->tree, fname))) {
1874                         printf("unlink of %s failed (%s)\n", 
1875                                fname, cli_errstr(cli->tree));
1876                         correct = False;
1877                 }
1878                 free(fname);
1879                 printf("%6d\r", i);
1880         }
1881         printf("%6d\n", 0);
1882
1883         printf("maxfid test finished\n");
1884         if (!torture_close_connection(cli)) {
1885                 correct = False;
1886         }
1887         return correct;
1888 }
1889
1890 /* send smb negprot commands, not reading the response */
1891 static BOOL run_negprot_nowait(int dummy)
1892 {
1893         int i;
1894         struct cli_state *cli;
1895         BOOL correct = True;
1896
1897         printf("starting negprot nowait test\n");
1898
1899         cli = open_nbt_connection();
1900         if (!cli) {
1901                 return False;
1902         }
1903
1904         printf("Establishing protocol negotiations - connect with another client\n");
1905
1906         for (i=0;i<50000;i++) {
1907                 smb_negprot_send(cli->transport, PROTOCOL_NT1);
1908         }
1909
1910         if (!torture_close_connection(cli)) {
1911                 correct = False;
1912         }
1913
1914         printf("finished negprot nowait test\n");
1915
1916         return correct;
1917 }
1918
1919
1920 /*
1921   This checks how the getatr calls works
1922 */
1923 static BOOL run_attrtest(int dummy)
1924 {
1925         struct cli_state *cli;
1926         int fnum;
1927         time_t t, t2;
1928         const char *fname = "\\attrib123456789.tst";
1929         BOOL correct = True;
1930
1931         printf("starting attrib test\n");
1932
1933         if (!torture_open_connection(&cli)) {
1934                 return False;
1935         }
1936
1937         cli_unlink(cli->tree, fname);
1938         fnum = cli_open(cli->tree, fname, 
1939                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1940         cli_close(cli->tree, fnum);
1941
1942         if (NT_STATUS_IS_ERR(cli_getatr(cli->tree, fname, NULL, NULL, &t))) {
1943                 printf("getatr failed (%s)\n", cli_errstr(cli->tree));
1944                 correct = False;
1945         }
1946
1947         printf("New file time is %s", ctime(&t));
1948
1949         if (abs(t - time(NULL)) > 60*60*24*10) {
1950                 printf("ERROR: SMBgetatr bug. time is %s",
1951                        ctime(&t));
1952                 t = time(NULL);
1953                 correct = False;
1954         }
1955
1956         t2 = t-60*60*24; /* 1 day ago */
1957
1958         printf("Setting file time to %s", ctime(&t2));
1959
1960         if (NT_STATUS_IS_ERR(cli_setatr(cli->tree, fname, 0, t2))) {
1961                 printf("setatr failed (%s)\n", cli_errstr(cli->tree));
1962                 correct = True;
1963         }
1964
1965         if (NT_STATUS_IS_ERR(cli_getatr(cli->tree, fname, NULL, NULL, &t))) {
1966                 printf("getatr failed (%s)\n", cli_errstr(cli->tree));
1967                 correct = True;
1968         }
1969
1970         printf("Retrieved file time as %s", ctime(&t));
1971
1972         if (t != t2) {
1973                 printf("ERROR: getatr/setatr bug. times are\n%s",
1974                        ctime(&t));
1975                 printf("%s", ctime(&t2));
1976                 correct = True;
1977         }
1978
1979         cli_unlink(cli->tree, fname);
1980
1981         if (!torture_close_connection(cli)) {
1982                 correct = False;
1983         }
1984
1985         printf("attrib test finished\n");
1986
1987         return correct;
1988 }
1989
1990
1991 /*
1992   This checks a couple of trans2 calls
1993 */
1994 static BOOL run_trans2test(int dummy)
1995 {
1996         struct cli_state *cli;
1997         int fnum;
1998         size_t size;
1999         time_t c_time, a_time, m_time, w_time, m_time2;
2000         const char *fname = "\\trans2.tst";
2001         const char *dname = "\\trans2";
2002         const char *fname2 = "\\trans2\\trans2.tst";
2003         const char *pname;
2004         BOOL correct = True;
2005
2006         printf("starting trans2 test\n");
2007
2008         if (!torture_open_connection(&cli)) {
2009                 return False;
2010         }
2011
2012         cli_unlink(cli->tree, fname);
2013
2014         printf("Testing qfileinfo\n");
2015         
2016         fnum = cli_open(cli->tree, fname, 
2017                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2018         if (NT_STATUS_IS_ERR(cli_qfileinfo(cli->tree, fnum, NULL, &size, &c_time, &a_time, &m_time,
2019                            NULL, NULL))) {
2020                 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(cli->tree));
2021                 correct = False;
2022         }
2023
2024         printf("Testing NAME_INFO\n");
2025
2026         if (NT_STATUS_IS_ERR(cli_qfilename(cli->tree, fnum, &pname))) {
2027                 printf("ERROR: qfilename failed (%s)\n", cli_errstr(cli->tree));
2028                 correct = False;
2029         }
2030
2031         if (!pname || strcmp(pname, fname)) {
2032                 printf("qfilename gave different name? [%s] [%s]\n",
2033                        fname, pname);
2034                 correct = False;
2035         }
2036
2037         cli_close(cli->tree, fnum);
2038         cli_unlink(cli->tree, fname);
2039
2040         fnum = cli_open(cli->tree, fname, 
2041                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2042         if (fnum == -1) {
2043                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli->tree));
2044                 return False;
2045         }
2046         cli_close(cli->tree, fnum);
2047
2048         printf("Checking for sticky create times\n");
2049
2050         if (NT_STATUS_IS_ERR(cli_qpathinfo(cli->tree, fname, &c_time, &a_time, &m_time, &size, NULL))) {
2051                 printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(cli->tree));
2052                 correct = False;
2053         } else {
2054                 if (c_time != m_time) {
2055                         printf("create time=%s", ctime(&c_time));
2056                         printf("modify time=%s", ctime(&m_time));
2057                         printf("This system appears to have sticky create times\n");
2058                 }
2059                 if (a_time % (60*60) == 0) {
2060                         printf("access time=%s", ctime(&a_time));
2061                         printf("This system appears to set a midnight access time\n");
2062                         correct = False;
2063                 }
2064
2065                 if (abs(m_time - time(NULL)) > 60*60*24*7) {
2066                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
2067                         correct = False;
2068                 }
2069         }
2070
2071
2072         cli_unlink(cli->tree, fname);
2073         fnum = cli_open(cli->tree, fname, 
2074                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2075         cli_close(cli->tree, fnum);
2076         if (NT_STATUS_IS_ERR(cli_qpathinfo2(cli->tree, fname, &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
2077                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(cli->tree));
2078                 correct = False;
2079         } else {
2080                 if (w_time < 60*60*24*2) {
2081                         printf("write time=%s", ctime(&w_time));
2082                         printf("This system appears to set a initial 0 write time\n");
2083                         correct = False;
2084                 }
2085         }
2086
2087         cli_unlink(cli->tree, fname);
2088
2089
2090         /* check if the server updates the directory modification time
2091            when creating a new file */
2092         if (NT_STATUS_IS_ERR(cli_mkdir(cli->tree, dname))) {
2093                 printf("ERROR: mkdir failed (%s)\n", cli_errstr(cli->tree));
2094                 correct = False;
2095         }
2096         sleep(3);
2097         if (NT_STATUS_IS_ERR(cli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
2098                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(cli->tree));
2099                 correct = False;
2100         }
2101
2102         fnum = cli_open(cli->tree, fname2, 
2103                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2104         cli_write(cli->tree, fnum,  0, (char *)&fnum, 0, sizeof(fnum));
2105         cli_close(cli->tree, fnum);
2106         if (NT_STATUS_IS_ERR(cli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time2, &w_time, &size, NULL, NULL))) {
2107                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(cli->tree));
2108                 correct = False;
2109         } else {
2110                 if (m_time2 == m_time) {
2111                         printf("This system does not update directory modification times\n");
2112                         correct = False;
2113                 }
2114         }
2115         cli_unlink(cli->tree, fname2);
2116         cli_rmdir(cli->tree, dname);
2117
2118         if (!torture_close_connection(cli)) {
2119                 correct = False;
2120         }
2121
2122         printf("trans2 test finished\n");
2123
2124         return correct;
2125 }
2126
2127 /*
2128   Test delete on close semantics.
2129  */
2130 static BOOL run_deletetest(int dummy)
2131 {
2132         struct cli_state *cli1;
2133         struct cli_state *cli2 = NULL;
2134         const char *fname = "\\delete.file";
2135         int fnum1 = -1;
2136         int fnum2 = -1;
2137         BOOL correct = True;
2138         
2139         printf("starting delete test\n");
2140         
2141         if (!torture_open_connection(&cli1)) {
2142                 return False;
2143         }
2144         
2145         /* Test 1 - this should delete the file on close. */
2146         
2147         cli_setatr(cli1->tree, fname, 0, 0);
2148         cli_unlink(cli1->tree, fname);
2149         
2150         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
2151                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 
2152                                    NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2153         
2154         if (fnum1 == -1) {
2155                 printf("[1] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2156                 correct = False;
2157                 goto fail;
2158         }
2159         
2160         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2161                 printf("[1] close failed (%s)\n", cli_errstr(cli1->tree));
2162                 correct = False;
2163                 goto fail;
2164         }
2165
2166         fnum1 = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
2167         if (fnum1 != -1) {
2168                 printf("[1] open of %s succeeded (should fail)\n", fname);
2169                 correct = False;
2170                 goto fail;
2171         }
2172         
2173         printf("first delete on close test succeeded.\n");
2174         
2175         /* Test 2 - this should delete the file on close. */
2176         
2177         cli_setatr(cli1->tree, fname, 0, 0);
2178         cli_unlink(cli1->tree, fname);
2179         
2180         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS,
2181                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, 
2182                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2183         
2184         if (fnum1 == -1) {
2185                 printf("[2] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2186                 correct = False;
2187                 goto fail;
2188         }
2189         
2190         if (NT_STATUS_IS_ERR(cli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2191                 printf("[2] setting delete_on_close failed (%s)\n", cli_errstr(cli1->tree));
2192                 correct = False;
2193                 goto fail;
2194         }
2195         
2196         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2197                 printf("[2] close failed (%s)\n", cli_errstr(cli1->tree));
2198                 correct = False;
2199                 goto fail;
2200         }
2201         
2202         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2203         if (fnum1 != -1) {
2204                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
2205                 if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2206                         printf("[2] close failed (%s)\n", cli_errstr(cli1->tree));
2207                         correct = False;
2208                         goto fail;
2209                 }
2210                 cli_unlink(cli1->tree, fname);
2211         } else
2212                 printf("second delete on close test succeeded.\n");
2213         
2214         /* Test 3 - ... */
2215         cli_setatr(cli1->tree, fname, 0, 0);
2216         cli_unlink(cli1->tree, fname);
2217
2218         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
2219                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2220
2221         if (fnum1 == -1) {
2222                 printf("[3] open - 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2223                 correct = False;
2224                 goto fail;
2225         }
2226
2227         /* This should fail with a sharing violation - open for delete is only compatible
2228            with SHARE_DELETE. */
2229
2230         fnum2 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
2231                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
2232                                    NTCREATEX_DISP_OPEN, 0, 0);
2233
2234         if (fnum2 != -1) {
2235                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
2236                 correct = False;
2237                 goto fail;
2238         }
2239
2240         /* This should succeed. */
2241
2242         fnum2 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
2243                         NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN, 0, 0);
2244
2245         if (fnum2 == -1) {
2246                 printf("[3] open  - 2 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2247                 correct = False;
2248                 goto fail;
2249         }
2250
2251         if (NT_STATUS_IS_ERR(cli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2252                 printf("[3] setting delete_on_close failed (%s)\n", cli_errstr(cli1->tree));
2253                 correct = False;
2254                 goto fail;
2255         }
2256         
2257         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2258                 printf("[3] close 1 failed (%s)\n", cli_errstr(cli1->tree));
2259                 correct = False;
2260                 goto fail;
2261         }
2262         
2263         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum2))) {
2264                 printf("[3] close 2 failed (%s)\n", cli_errstr(cli1->tree));
2265                 correct = False;
2266                 goto fail;
2267         }
2268         
2269         /* This should fail - file should no longer be there. */
2270
2271         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2272         if (fnum1 != -1) {
2273                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
2274                 if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2275                         printf("[3] close failed (%s)\n", cli_errstr(cli1->tree));
2276                 }
2277                 cli_unlink(cli1->tree, fname);
2278                 correct = False;
2279                 goto fail;
2280         } else
2281                 printf("third delete on close test succeeded.\n");
2282
2283         /* Test 4 ... */
2284         cli_setatr(cli1->tree, fname, 0, 0);
2285         cli_unlink(cli1->tree, fname);
2286
2287         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, 
2288                                    SA_RIGHT_FILE_READ_DATA  | 
2289                                    SA_RIGHT_FILE_WRITE_DATA |
2290                                    STD_RIGHT_DELETE_ACCESS,
2291                                    FILE_ATTRIBUTE_NORMAL, 
2292                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
2293                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2294                                                                 
2295         if (fnum1 == -1) {
2296                 printf("[4] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2297                 correct = False;
2298                 goto fail;
2299         }
2300
2301         /* This should succeed. */
2302         fnum2 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ,
2303                                    FILE_ATTRIBUTE_NORMAL, 
2304                                    NTCREATEX_SHARE_ACCESS_READ  | 
2305                                    NTCREATEX_SHARE_ACCESS_WRITE |
2306                                    NTCREATEX_SHARE_ACCESS_DELETE, 
2307                                    NTCREATEX_DISP_OPEN, 0, 0);
2308         if (fnum2 == -1) {
2309                 printf("[4] open  - 2 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2310                 correct = False;
2311                 goto fail;
2312         }
2313         
2314         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum2))) {
2315                 printf("[4] close - 1 failed (%s)\n", cli_errstr(cli1->tree));
2316                 correct = False;
2317                 goto fail;
2318         }
2319         
2320         if (NT_STATUS_IS_ERR(cli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2321                 printf("[4] setting delete_on_close failed (%s)\n", cli_errstr(cli1->tree));
2322                 correct = False;
2323                 goto fail;
2324         }
2325         
2326         /* This should fail - no more opens once delete on close set. */
2327         fnum2 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ,
2328                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
2329                                    NTCREATEX_DISP_OPEN, 0, 0);
2330         if (fnum2 != -1) {
2331                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
2332                 correct = False;
2333                 goto fail;
2334         } else
2335                 printf("fourth delete on close test succeeded.\n");
2336         
2337         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2338                 printf("[4] close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2339                 correct = False;
2340                 goto fail;
2341         }
2342         
2343         /* Test 5 ... */
2344         cli_setatr(cli1->tree, fname, 0, 0);
2345         cli_unlink(cli1->tree, fname);
2346         
2347         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2348         if (fnum1 == -1) {
2349                 printf("[5] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2350                 correct = False;
2351                 goto fail;
2352         }
2353
2354         /* This should fail - only allowed on NT opens with DELETE access. */
2355
2356         if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2357                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
2358                 correct = False;
2359                 goto fail;
2360         }
2361
2362         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2363                 printf("[5] close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2364                 correct = False;
2365                 goto fail;
2366         }
2367         
2368         printf("fifth delete on close test succeeded.\n");
2369         
2370         /* Test 6 ... */
2371         cli_setatr(cli1->tree, fname, 0, 0);
2372         cli_unlink(cli1->tree, fname);
2373         
2374         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, 
2375                                    SA_RIGHT_FILE_READ_DATA | SA_RIGHT_FILE_WRITE_DATA,
2376                                    FILE_ATTRIBUTE_NORMAL, 
2377                                    NTCREATEX_SHARE_ACCESS_READ  |
2378                                    NTCREATEX_SHARE_ACCESS_WRITE |
2379                                    NTCREATEX_SHARE_ACCESS_DELETE,
2380                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2381         
2382         if (fnum1 == -1) {
2383                 printf("[6] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2384                 correct = False;
2385                 goto fail;
2386         }
2387         
2388         /* This should fail - only allowed on NT opens with DELETE access. */
2389         
2390         if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2391                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
2392                 correct = False;
2393                 goto fail;
2394         }
2395
2396         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2397                 printf("[6] close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2398                 correct = False;
2399                 goto fail;
2400         }
2401
2402         printf("sixth delete on close test succeeded.\n");
2403         
2404         /* Test 7 ... */
2405         cli_setatr(cli1->tree, fname, 0, 0);
2406         cli_unlink(cli1->tree, fname);
2407         
2408         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, 
2409                                    SA_RIGHT_FILE_READ_DATA  | 
2410                                    SA_RIGHT_FILE_WRITE_DATA |
2411                                    STD_RIGHT_DELETE_ACCESS,
2412                                    FILE_ATTRIBUTE_NORMAL, 0, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2413                                                                 
2414         if (fnum1 == -1) {
2415                 printf("[7] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2416                 correct = False;
2417                 goto fail;
2418         }
2419
2420         if (NT_STATUS_IS_ERR(cli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2421                 printf("[7] setting delete_on_close on file failed !\n");
2422                 correct = False;
2423                 goto fail;
2424         }
2425         
2426         if (NT_STATUS_IS_ERR(cli_nt_delete_on_close(cli1->tree, fnum1, False))) {
2427                 printf("[7] unsetting delete_on_close on file failed !\n");
2428                 correct = False;
2429                 goto fail;
2430         }
2431
2432         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2433                 printf("[7] close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2434                 correct = False;
2435                 goto fail;
2436         }
2437         
2438         /* This next open should succeed - we reset the flag. */
2439         
2440         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2441         if (fnum1 == -1) {
2442                 printf("[5] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2443                 correct = False;
2444                 goto fail;
2445         }
2446
2447         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2448                 printf("[7] close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2449                 correct = False;
2450                 goto fail;
2451         }
2452
2453         printf("seventh delete on close test succeeded.\n");
2454         
2455         /* Test 7 ... */
2456         cli_setatr(cli1->tree, fname, 0, 0);
2457         cli_unlink(cli1->tree, fname);
2458         
2459         if (!torture_open_connection(&cli2)) {
2460                 printf("[8] failed to open second connection.\n");
2461                 correct = False;
2462                 goto fail;
2463         }
2464
2465         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|STD_RIGHT_DELETE_ACCESS,
2466                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
2467                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2468         
2469         if (fnum1 == -1) {
2470                 printf("[8] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2471                 correct = False;
2472                 goto fail;
2473         }
2474
2475         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|STD_RIGHT_DELETE_ACCESS,
2476                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
2477                                    NTCREATEX_DISP_OPEN, 0, 0);
2478         
2479         if (fnum2 == -1) {
2480                 printf("[8] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2481                 correct = False;
2482                 goto fail;
2483         }
2484
2485         if (NT_STATUS_IS_ERR(cli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2486                 printf("[8] setting delete_on_close on file failed !\n");
2487                 correct = False;
2488                 goto fail;
2489         }
2490         
2491         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2492                 printf("[8] close - 1 failed (%s)\n", cli_errstr(cli1->tree));
2493                 correct = False;
2494                 goto fail;
2495         }
2496
2497         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum2))) {
2498                 printf("[8] close - 2 failed (%s)\n", cli_errstr(cli2->tree));
2499                 correct = False;
2500                 goto fail;
2501         }
2502
2503         /* This should fail.. */
2504         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2505         if (fnum1 != -1) {
2506                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
2507                 goto fail;
2508                 correct = False;
2509         } else
2510                 printf("eighth delete on close test succeeded.\n");
2511
2512         /* This should fail - we need to set DELETE_ACCESS. */
2513         fnum1 = cli_nt_create_full(cli1->tree, fname, 0,SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA,
2514                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2515         
2516         if (fnum1 != -1) {
2517                 printf("[9] open of %s succeeded should have failed!\n", fname);
2518                 correct = False;
2519                 goto fail;
2520         }
2521
2522         printf("ninth delete on close test succeeded.\n");
2523
2524         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|STD_RIGHT_DELETE_ACCESS,
2525                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2526         if (fnum1 == -1) {
2527                 printf("[10] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2528                 correct = False;
2529                 goto fail;
2530         }
2531
2532         /* This should delete the file. */
2533         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2534                 printf("[10] close failed (%s)\n", cli_errstr(cli1->tree));
2535                 correct = False;
2536                 goto fail;
2537         }
2538
2539         /* This should fail.. */
2540         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2541         if (fnum1 != -1) {
2542                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
2543                 goto fail;
2544                 correct = False;
2545         } else
2546                 printf("tenth delete on close test succeeded.\n");
2547         printf("finished delete test\n");
2548
2549   fail:
2550         /* FIXME: This will crash if we aborted before cli2 got
2551          * intialized, because these functions don't handle
2552          * uninitialized connections. */
2553                 
2554         cli_close(cli1->tree, fnum1);
2555         cli_close(cli1->tree, fnum2);
2556         cli_setatr(cli1->tree, fname, 0, 0);
2557         cli_unlink(cli1->tree, fname);
2558
2559         if (!torture_close_connection(cli1)) {
2560                 correct = False;
2561         }
2562         if (!torture_close_connection(cli2)) {
2563                 correct = False;
2564         }
2565         return correct;
2566 }
2567
2568
2569 /*
2570   print out server properties
2571  */
2572 static BOOL run_properties(int dummy)
2573 {
2574         struct cli_state *cli;
2575         BOOL correct = True;
2576         
2577         printf("starting properties test\n");
2578         
2579         ZERO_STRUCT(cli);
2580
2581         if (!torture_open_connection(&cli)) {
2582                 return False;
2583         }
2584         
2585         d_printf("Capabilities 0x%08x\n", cli->transport->negotiate.capabilities);
2586
2587         if (!torture_close_connection(cli)) {
2588                 correct = False;
2589         }
2590
2591         return correct;
2592 }
2593
2594
2595
2596 /* FIRST_DESIRED_ACCESS   0xf019f */
2597 #define FIRST_DESIRED_ACCESS   SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|SA_RIGHT_FILE_APPEND_DATA|\
2598                                SA_RIGHT_FILE_READ_EA|                           /* 0xf */ \
2599                                SA_RIGHT_FILE_WRITE_EA|SA_RIGHT_FILE_READ_ATTRIBUTES|     /* 0x90 */ \
2600                                SA_RIGHT_FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
2601                                STD_RIGHT_DELETE_ACCESS|STD_RIGHT_READ_CONTROL_ACCESS|\
2602                                STD_RIGHT_WRITE_DAC_ACCESS|STD_RIGHT_WRITE_OWNER_ACCESS     /* 0xf0000 */
2603 /* SECOND_DESIRED_ACCESS  0xe0080 */
2604 #define SECOND_DESIRED_ACCESS  SA_RIGHT_FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
2605                                STD_RIGHT_READ_CONTROL_ACCESS|STD_RIGHT_WRITE_DAC_ACCESS|\
2606                                STD_RIGHT_WRITE_OWNER_ACCESS                      /* 0xe0000 */
2607
2608 #if 0
2609 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
2610                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
2611                                SA_RIGHT_FILE_READ_DATA|\
2612                                WRITE_OWNER_ACCESS                      /* */
2613 #endif
2614
2615 /*
2616   Test ntcreate calls made by xcopy
2617  */
2618 static BOOL run_xcopy(int dummy)
2619 {
2620         struct cli_state *cli1;
2621         const char *fname = "\\test.txt";
2622         BOOL correct = True;
2623         int fnum1, fnum2;
2624
2625         printf("starting xcopy test\n");
2626         
2627         if (!torture_open_connection(&cli1)) {
2628                 return False;
2629         }
2630         
2631         fnum1 = cli_nt_create_full(cli1->tree, fname, 0,
2632                                    FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
2633                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 
2634                                    0x4044, 0);
2635
2636         if (fnum1 == -1) {
2637                 printf("First open failed - %s\n", cli_errstr(cli1->tree));
2638                 return False;
2639         }
2640
2641         fnum2 = cli_nt_create_full(cli1->tree, fname, 0,
2642                                    SECOND_DESIRED_ACCESS, 0,
2643                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN, 
2644                                    0x200000, 0);
2645         if (fnum2 == -1) {
2646                 printf("second open failed - %s\n", cli_errstr(cli1->tree));
2647                 return False;
2648         }
2649         
2650         if (!torture_close_connection(cli1)) {
2651                 correct = False;
2652         }
2653         
2654         return correct;
2655 }
2656
2657 /*
2658   Test rename on files open with share delete and no share delete.
2659  */
2660 static BOOL run_rename(int dummy)
2661 {
2662         struct cli_state *cli1;
2663         const char *fname = "\\test.txt";
2664         const char *fname1 = "\\test1.txt";
2665         BOOL correct = True;
2666         int fnum1;
2667
2668         printf("starting rename test\n");
2669         
2670         if (!torture_open_connection(&cli1)) {
2671                 return False;
2672         }
2673         
2674         cli_unlink(cli1->tree, fname);
2675         cli_unlink(cli1->tree, fname1);
2676         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
2677                                    NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2678
2679         if (fnum1 == -1) {
2680                 printf("First open failed - %s\n", cli_errstr(cli1->tree));
2681                 return False;
2682         }
2683
2684         if (NT_STATUS_IS_ERR(cli_rename(cli1->tree, fname, fname1))) {
2685                 printf("First rename failed (this is correct) - %s\n", cli_errstr(cli1->tree));
2686         } else {
2687                 printf("First rename succeeded - this should have failed !\n");
2688                 correct = False;
2689         }
2690
2691         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2692                 printf("close - 1 failed (%s)\n", cli_errstr(cli1->tree));
2693                 return False;
2694         }
2695
2696         cli_unlink(cli1->tree, fname);
2697         cli_unlink(cli1->tree, fname1);
2698         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
2699 #if 0
2700                                    NTCREATEX_SHARE_ACCESS_DELETE|NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2701 #else
2702                                    NTCREATEX_SHARE_ACCESS_DELETE|NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2703 #endif
2704
2705         if (fnum1 == -1) {
2706                 printf("Second open failed - %s\n", cli_errstr(cli1->tree));
2707                 return False;
2708         }
2709
2710         if (NT_STATUS_IS_ERR(cli_rename(cli1->tree, fname, fname1))) {
2711                 printf("Second rename failed - this should have succeeded - %s\n", cli_errstr(cli1->tree));
2712                 correct = False;
2713         } else {
2714                 printf("Second rename succeeded\n");
2715         }
2716
2717         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2718                 printf("close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2719                 return False;
2720         }
2721
2722         cli_unlink(cli1->tree, fname);
2723         cli_unlink(cli1->tree, fname1);
2724
2725         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_READ_CONTROL_ACCESS, FILE_ATTRIBUTE_NORMAL,
2726                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2727
2728         if (fnum1 == -1) {
2729                 printf("Third open failed - %s\n", cli_errstr(cli1->tree));
2730                 return False;
2731         }
2732
2733
2734 #if 0
2735   {
2736   int fnum2;
2737
2738         fnum2 = cli_nt_create_full(cli1->tree, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
2739                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2740
2741         if (fnum2 == -1) {
2742                 printf("Fourth open failed - %s\n", cli_errstr(cli1->tree));
2743                 return False;
2744         }
2745         if (!cli_nt_delete_on_close(cli1->tree, fnum2, True)) {
2746                 printf("[8] setting delete_on_close on file failed !\n");
2747                 return False;
2748         }
2749         
2750         if (!cli_close(cli1->tree, fnum2)) {
2751                 printf("close - 4 failed (%s)\n", cli_errstr(cli1->tree));
2752                 return False;
2753         }
2754   }
2755 #endif
2756
2757         if (NT_STATUS_IS_ERR(cli_rename(cli1->tree, fname, fname1))) {
2758                 printf("Third rename failed - this should have succeeded - %s\n", cli_errstr(cli1->tree));
2759                 correct = False;
2760         } else {
2761                 printf("Third rename succeeded\n");
2762         }
2763
2764         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2765                 printf("close - 3 failed (%s)\n", cli_errstr(cli1->tree));
2766                 return False;
2767         }
2768
2769         cli_unlink(cli1->tree, fname);
2770         cli_unlink(cli1->tree, fname1);
2771
2772         if (!torture_close_connection(cli1)) {
2773                 correct = False;
2774         }
2775         
2776         return correct;
2777 }
2778
2779 static BOOL run_pipe_number(int dummy)
2780 {
2781         struct cli_state *cli1;
2782         const char *pipe_name = "\\WKSSVC";
2783         int fnum;
2784         int num_pipes = 0;
2785
2786         printf("starting pipenumber test\n");
2787         if (!torture_open_connection(&cli1)) {
2788                 return False;
2789         }
2790
2791         while(1) {
2792                 fnum = cli_nt_create_full(cli1->tree, pipe_name, 0, SA_RIGHT_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
2793                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OPEN_IF, 0, 0);
2794
2795                 if (fnum == -1) {
2796                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, cli_errstr(cli1->tree));
2797                         break;
2798                 }
2799                 num_pipes++;
2800         }
2801
2802         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
2803         torture_close_connection(cli1);
2804         return True;
2805 }
2806
2807
2808
2809
2810 /*
2811   open N connections to the server and just hold them open
2812   used for testing performance when there are N idle users
2813   already connected
2814  */
2815  static BOOL torture_holdcon(int dummy)
2816 {
2817         int i;
2818         struct cli_state **cli;
2819         int num_dead = 0;
2820
2821         printf("Opening %d connections\n", torture_numops);
2822         
2823         cli = malloc(sizeof(struct cli_state *) * torture_numops);
2824
2825         for (i=0;i<torture_numops;i++) {
2826                 if (!torture_open_connection(&cli[i])) {
2827                         return False;
2828                 }
2829                 printf("opened %d connections\r", i);
2830                 fflush(stdout);
2831         }
2832
2833         printf("\nStarting pings\n");
2834
2835         while (1) {
2836                 for (i=0;i<torture_numops;i++) {
2837                         NTSTATUS status;
2838                         if (cli[i]) {
2839                                 status = cli_chkpath(cli[i]->tree, "\\");
2840                                 if (!NT_STATUS_IS_OK(status)) {
2841                                         printf("Connection %d is dead\n", i);
2842                                         cli[i] = NULL;
2843                                         num_dead++;
2844                                 }
2845                                 usleep(100);
2846                         }
2847                 }
2848
2849                 if (num_dead == torture_numops) {
2850                         printf("All connections dead - finishing\n");
2851                         break;
2852                 }
2853
2854                 printf(".");
2855                 fflush(stdout);
2856         }
2857
2858         return True;
2859 }
2860
2861 /*
2862   Try with a wrong vuid and check error message.
2863  */
2864
2865 static BOOL run_vuidtest(int dummy)
2866 {
2867         struct cli_state *cli;
2868         const char *fname = "\\vuid.tst";
2869         int fnum;
2870         size_t size;
2871         time_t c_time, a_time, m_time;
2872         BOOL correct = True;
2873
2874         uint16_t orig_vuid;
2875         NTSTATUS result;
2876
2877         printf("starting vuid test\n");
2878
2879         if (!torture_open_connection(&cli)) {
2880                 return False;
2881         }
2882
2883         cli_unlink(cli->tree, fname);
2884
2885         fnum = cli_open(cli->tree, fname, 
2886                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2887
2888         orig_vuid = cli->session->vuid;
2889
2890         cli->session->vuid += 1234;
2891
2892         printf("Testing qfileinfo with wrong vuid\n");
2893         
2894         if (NT_STATUS_IS_OK(result = cli_qfileinfo(cli->tree, fnum, NULL,
2895                                                    &size, &c_time, &a_time,
2896                                                    &m_time, NULL, NULL))) {
2897                 printf("ERROR: qfileinfo passed with wrong vuid\n");
2898                 correct = False;
2899         }
2900
2901         if ( (cli->transport->error.etype != ETYPE_DOS) ||
2902              (cli->transport->error.e.dos.eclass != ERRSRV) ||
2903              (cli->transport->error.e.dos.ecode != ERRbaduid) ) {
2904                 printf("ERROR: qfileinfo should have returned DOS error "
2905                        "ERRSRV:ERRbaduid\n  but returned %s\n",
2906                        cli_errstr(cli->tree));
2907                 correct = False;
2908         }
2909
2910         cli->session->vuid -= 1234;
2911
2912         if (NT_STATUS_IS_ERR(cli_close(cli->tree, fnum))) {
2913                 printf("close failed (%s)\n", cli_errstr(cli->tree));
2914                 correct = False;
2915         }
2916
2917         cli_unlink(cli->tree, fname);
2918
2919         if (!torture_close_connection(cli)) {
2920                 correct = False;
2921         }
2922
2923         printf("vuid test finished\n");
2924
2925         return correct;
2926 }
2927
2928 /*
2929   Test open mode returns on read-only files.
2930  */
2931  static BOOL run_opentest(int dummy)
2932 {
2933         static struct cli_state *cli1;
2934         static struct cli_state *cli2;
2935         const char *fname = "\\readonly.file";
2936         int fnum1, fnum2;
2937         char buf[20];
2938         size_t fsize;
2939         BOOL correct = True;
2940         char *tmp_path;
2941         int failures = 0;
2942
2943         printf("starting open test\n");
2944         
2945         if (!torture_open_connection(&cli1)) {
2946                 return False;
2947         }
2948         
2949         cli_setatr(cli1->tree, fname, 0, 0);
2950         cli_unlink(cli1->tree, fname);
2951         
2952         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
2953         if (fnum1 == -1) {
2954                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2955                 return False;
2956         }
2957
2958         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2959                 printf("close2 failed (%s)\n", cli_errstr(cli1->tree));
2960                 return False;
2961         }
2962         
2963         if (NT_STATUS_IS_ERR(cli_setatr(cli1->tree, fname, FILE_ATTRIBUTE_READONLY, 0))) {
2964                 printf("cli_setatr failed (%s)\n", cli_errstr(cli1->tree));
2965                 CHECK_MAX_FAILURES(error_test1);
2966                 return False;
2967         }
2968         
2969         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
2970         if (fnum1 == -1) {
2971                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2972                 CHECK_MAX_FAILURES(error_test1);
2973                 return False;
2974         }
2975         
2976         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
2977         fnum2 = cli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
2978         
2979         if (check_error(__LINE__, cli1, ERRDOS, ERRnoaccess, 
2980                         NT_STATUS_ACCESS_DENIED)) {
2981                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
2982         }
2983         
2984         printf("finished open test 1\n");
2985 error_test1:
2986         cli_close(cli1->tree, fnum1);
2987         
2988         /* Now try not readonly and ensure ERRbadshare is returned. */
2989         
2990         cli_setatr(cli1->tree, fname, 0, 0);
2991         
2992         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
2993         if (fnum1 == -1) {
2994                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2995                 return False;
2996         }
2997         
2998         /* This will fail - but the error should be ERRshare. */
2999         fnum2 = cli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
3000         
3001         if (check_error(__LINE__, cli1, ERRDOS, ERRbadshare, 
3002                         NT_STATUS_SHARING_VIOLATION)) {
3003                 printf("correct error code ERRDOS/ERRbadshare returned\n");
3004         }
3005         
3006         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3007                 printf("close2 failed (%s)\n", cli_errstr(cli1->tree));
3008                 return False;
3009         }
3010         
3011         cli_unlink(cli1->tree, fname);
3012         
3013         printf("finished open test 2\n");
3014         
3015         /* Test truncate open disposition on file opened for read. */
3016         
3017         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
3018         if (fnum1 == -1) {
3019                 printf("(3) open (1) of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3020                 return False;
3021         }
3022         
3023         /* write 20 bytes. */
3024         
3025         memset(buf, '\0', 20);
3026
3027         if (cli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
3028                 printf("write failed (%s)\n", cli_errstr(cli1->tree));
3029                 correct = False;
3030         }
3031
3032         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3033                 printf("(3) close1 failed (%s)\n", cli_errstr(cli1->tree));
3034                 return False;
3035         }
3036         
3037         /* Ensure size == 20. */
3038         if (NT_STATUS_IS_ERR(cli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
3039                 printf("(3) getatr failed (%s)\n", cli_errstr(cli1->tree));
3040                 CHECK_MAX_FAILURES(error_test3);
3041                 return False;
3042         }
3043         
3044         if (fsize != 20) {
3045                 printf("(3) file size != 20\n");
3046                 CHECK_MAX_FAILURES(error_test3);
3047                 return False;
3048         }
3049
3050         /* Now test if we can truncate a file opened for readonly. */
3051         
3052         fnum1 = cli_open(cli1->tree, fname, O_RDONLY|O_TRUNC, DENY_NONE);
3053         if (fnum1 == -1) {
3054                 printf("(3) open (2) of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3055                 CHECK_MAX_FAILURES(error_test3);
3056                 return False;
3057         }
3058         
3059         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3060                 printf("close2 failed (%s)\n", cli_errstr(cli1->tree));
3061                 return False;
3062         }
3063
3064         /* Ensure size == 0. */
3065         if (NT_STATUS_IS_ERR(cli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
3066                 printf("(3) getatr failed (%s)\n", cli_errstr(cli1->tree));
3067                 CHECK_MAX_FAILURES(error_test3);
3068                 return False;
3069         }
3070
3071         if (fsize != 0) {
3072                 printf("(3) file size != 0\n");
3073                 CHECK_MAX_FAILURES(error_test3);
3074                 return False;
3075         }
3076         printf("finished open test 3\n");
3077 error_test3:    
3078         cli_unlink(cli1->tree, fname);
3079
3080
3081         printf("testing ctemp\n");
3082         fnum1 = cli_ctemp(cli1->tree, "\\", &tmp_path);
3083         if (fnum1 == -1) {
3084                 printf("ctemp failed (%s)\n", cli_errstr(cli1->tree));
3085                 CHECK_MAX_FAILURES(error_test4);
3086                 return False;
3087         }
3088         printf("ctemp gave path %s\n", tmp_path);
3089         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3090                 printf("close of temp failed (%s)\n", cli_errstr(cli1->tree));
3091         }
3092         if (NT_STATUS_IS_ERR(cli_unlink(cli1->tree, tmp_path))) {
3093                 printf("unlink of temp failed (%s)\n", cli_errstr(cli1->tree));
3094         }
3095 error_test4:    
3096         /* Test the non-io opens... */
3097
3098         if (!torture_open_connection(&cli2)) {
3099                 return False;
3100         }
3101         
3102         cli_setatr(cli2->tree, fname, 0, 0);
3103         cli_unlink(cli2->tree, fname);
3104         
3105         printf("TEST #1 testing 2 non-io opens (no delete)\n");
3106         
3107         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3108                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3109
3110         if (fnum1 == -1) {
3111                 printf("test 1 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3112                 CHECK_MAX_FAILURES(error_test10);
3113                 return False;
3114         }
3115
3116         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3117                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3118         if (fnum2 == -1) {
3119                 printf("test 1 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3120                 CHECK_MAX_FAILURES(error_test10);
3121                 return False;
3122         }
3123
3124         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3125                 printf("test 1 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3126                 return False;
3127         }
3128         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum2))) {
3129                 printf("test 1 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3130                 return False;
3131         }
3132
3133         printf("non-io open test #1 passed.\n");
3134 error_test10:
3135         cli_unlink(cli1->tree, fname);
3136
3137         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
3138         
3139         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3140                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3141
3142         if (fnum1 == -1) {
3143                 printf("test 2 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3144                 CHECK_MAX_FAILURES(error_test20);
3145                 return False;
3146         }
3147
3148         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3149                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3150
3151         if (fnum2 == -1) {
3152                 printf("test 2 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3153                 CHECK_MAX_FAILURES(error_test20);
3154                 return False;
3155         }
3156
3157         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3158                 printf("test 1 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3159                 return False;
3160         }
3161         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum2))) {
3162                 printf("test 1 close 2 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3163                 return False;
3164         }
3165
3166         printf("non-io open test #2 passed.\n");
3167 error_test20:
3168         cli_unlink(cli1->tree, fname);
3169
3170         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
3171         
3172         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3173                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3174
3175         if (fnum1 == -1) {
3176                 printf("test 3 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3177                 CHECK_MAX_FAILURES(error_test30);
3178                 return False;
3179         }
3180
3181         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3182                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3183
3184         if (fnum2 == -1) {
3185                 printf("test 3 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3186                 CHECK_MAX_FAILURES(error_test30);
3187                 return False;
3188         }
3189
3190         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3191                 printf("test 3 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3192                 return False;
3193         }
3194         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum2))) {
3195                 printf("test 3 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3196                 return False;
3197         }
3198
3199         printf("non-io open test #3 passed.\n");
3200 error_test30:
3201         cli_unlink(cli1->tree, fname);
3202
3203         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
3204         
3205         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3206                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3207
3208         if (fnum1 == -1) {
3209                 printf("test 4 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3210                 CHECK_MAX_FAILURES(error_test40);
3211                 return False;
3212         }
3213
3214         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3215                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3216
3217         if (fnum2 != -1) {
3218                 printf("test 4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, cli_errstr(cli2->tree));
3219                 CHECK_MAX_FAILURES(error_test40);
3220                 return False;
3221         }
3222
3223         printf("test 4 open 2 of %s gave %s (correct error should be %s)\n", fname, cli_errstr(cli2->tree), "sharing violation");
3224
3225         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3226                 printf("test 4 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3227                 return False;
3228         }
3229
3230         printf("non-io open test #4 passed.\n");
3231 error_test40:
3232         cli_unlink(cli1->tree, fname);
3233
3234         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
3235         
3236         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3237                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3238
3239         if (fnum1 == -1) {
3240                 printf("test 5 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3241                 CHECK_MAX_FAILURES(error_test50);
3242                 return False;
3243         }
3244
3245         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3246                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3247
3248         if (fnum2 == -1) {
3249                 printf("test 5 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3250                 CHECK_MAX_FAILURES(error_test50);
3251                 return False;
3252         }
3253
3254         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3255                 printf("test 5 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3256                 return False;
3257         }
3258
3259         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum2))) {
3260                 printf("test 5 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3261                 return False;
3262         }
3263
3264         printf("non-io open test #5 passed.\n");
3265 error_test50:
3266         printf("TEST #6 testing 1 non-io open, one io open\n");
3267         
3268         cli_unlink(cli1->tree, fname);
3269
3270         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
3271                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3272
3273         if (fnum1 == -1) {
3274                 printf("test 6 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3275                 CHECK_MAX_FAILURES(error_test60);
3276                 return False;
3277         }
3278
3279         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3280                                    NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OPEN_IF, 0, 0);
3281
3282         if (fnum2 == -1) {
3283                 printf("test 6 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3284                 CHECK_MAX_FAILURES(error_test60);
3285                 return False;
3286         }
3287
3288         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3289                 printf("test 6 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3290                 return False;
3291         }
3292
3293         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum2))) {
3294                 printf("test 6 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3295                 return False;
3296         }
3297
3298         printf("non-io open test #6 passed.\n");
3299 error_test60:
3300         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
3301
3302         cli_unlink(cli1->tree, fname);
3303
3304         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
3305                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3306
3307         if (fnum1 == -1) {
3308                 printf("test 7 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3309                 CHECK_MAX_FAILURES(error_test70);
3310                 return False;
3311         }
3312
3313         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3314                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3315
3316         if (fnum2 != -1) {
3317                 printf("test 7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, cli_errstr(cli2->tree));
3318                 CHECK_MAX_FAILURES(error_test70);
3319                 return False;
3320         }
3321
3322         printf("test 7 open 2 of %s gave %s (correct error should be %s)\n", fname, cli_errstr(cli2->tree), "sharing violation");
3323
3324         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3325                 printf("test 7 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3326                 return False;
3327         }
3328
3329         printf("non-io open test #7 passed.\n");
3330
3331 error_test70:
3332
3333         printf("TEST #8 testing one normal open, followed by lock, followed by open with truncate\n");
3334
3335         cli_unlink(cli1->tree, fname);
3336
3337         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
3338         if (fnum1 == -1) {
3339                 printf("(8) open (1) of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3340                 return False;
3341         }
3342         
3343         /* write 20 bytes. */
3344         
3345         memset(buf, '\0', 20);
3346
3347         if (cli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
3348                 printf("(8) write failed (%s)\n", cli_errstr(cli1->tree));
3349                 correct = False;
3350         }
3351
3352         /* Ensure size == 20. */
3353         if (NT_STATUS_IS_ERR(cli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
3354                 printf("(8) getatr (1) failed (%s)\n", cli_errstr(cli1->tree));
3355                 CHECK_MAX_FAILURES(error_test80);
3356                 return False;
3357         }
3358         
3359         if (fsize != 20) {
3360                 printf("(8) file size != 20\n");
3361                 CHECK_MAX_FAILURES(error_test80);
3362                 return False;
3363         }
3364
3365         /* Get an exclusive lock on the open file. */
3366         if (NT_STATUS_IS_ERR(cli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
3367                 printf("(8) lock1 failed (%s)\n", cli_errstr(cli1->tree));
3368                 CHECK_MAX_FAILURES(error_test80);
3369                 return False;
3370         }
3371
3372         fnum2 = cli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
3373         if (fnum1 == -1) {
3374                 printf("(8) open (2) of %s with truncate failed (%s)\n", fname, cli_errstr(cli1->tree));
3375                 return False;
3376         }
3377
3378         /* Ensure size == 0. */
3379         if (NT_STATUS_IS_ERR(cli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
3380                 printf("(8) getatr (2) failed (%s)\n", cli_errstr(cli1->tree));
3381                 CHECK_MAX_FAILURES(error_test80);
3382                 return False;
3383         }
3384         
3385         if (fsize != 0) {
3386                 printf("(8) file size != 0\n");
3387                 CHECK_MAX_FAILURES(error_test80);
3388                 return False;
3389         }
3390
3391         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3392                 printf("(8) close1 failed (%s)\n", cli_errstr(cli1->tree));
3393                 return False;
3394         }
3395         
3396         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum2))) {
3397                 printf("(8) close1 failed (%s)\n", cli_errstr(cli1->tree));
3398                 return False;
3399         }
3400         
3401 error_test80:
3402
3403         printf("open test #8 passed.\n");
3404
3405         cli_unlink(cli1->tree, fname);
3406
3407         if (!torture_close_connection(cli1)) {
3408                 correct = False;
3409         }
3410         if (!torture_close_connection(cli2)) {
3411                 correct = False;
3412         }
3413         
3414         return correct;
3415 }
3416
3417
3418 static uint32_t open_attrs_table[] = {
3419                 FILE_ATTRIBUTE_NORMAL,
3420                 FILE_ATTRIBUTE_ARCHIVE,
3421                 FILE_ATTRIBUTE_READONLY,
3422                 FILE_ATTRIBUTE_HIDDEN,
3423                 FILE_ATTRIBUTE_SYSTEM,
3424
3425                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
3426                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
3427                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
3428                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
3429                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
3430                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
3431
3432                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
3433                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
3434                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
3435                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
3436 };
3437
3438 struct trunc_open_results {
3439         uint_t num;
3440         uint32_t init_attr;
3441         uint32_t trunc_attr;
3442         uint32_t result_attr;
3443 };
3444
3445 static struct trunc_open_results attr_results[] = {
3446         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
3447         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
3448         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
3449         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
3450         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
3451         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
3452         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3453         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3454         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
3455         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3456         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3457         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
3458         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3459         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3460         { 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 },
3461         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3462         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3463         { 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 },
3464         { 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 },
3465         { 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 },
3466         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3467         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3468         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
3469         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3470         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3471         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
3472 };
3473
3474 static BOOL run_openattrtest(int dummy)
3475 {
3476         struct cli_state *cli1;
3477         const char *fname = "\\openattr.file";
3478         int fnum1;
3479         BOOL correct = True;
3480         uint16_t attr;
3481         uint_t i, j, k, l;
3482         int failures = 0;
3483
3484         printf("starting open attr test\n");
3485         
3486         if (!torture_open_connection(&cli1)) {
3487                 return False;
3488         }
3489         
3490         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
3491                 cli_setatr(cli1->tree, fname, 0, 0);
3492                 cli_unlink(cli1->tree, fname);
3493                 fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_WRITE_DATA, open_attrs_table[i],
3494                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3495
3496                 if (fnum1 == -1) {
3497                         printf("open %d (1) of %s failed (%s)\n", i, fname, cli_errstr(cli1->tree));
3498                         return False;
3499                 }
3500
3501                 if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3502                         printf("close %d (1) of %s failed (%s)\n", i, fname, cli_errstr(cli1->tree));
3503                         return False;
3504                 }
3505
3506                 for (j = 0; j < ARRAY_SIZE(open_attrs_table); j++) {
3507                         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, 
3508                                                    SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA, 
3509                                                    open_attrs_table[j],
3510                                                    NTCREATEX_SHARE_ACCESS_NONE, 
3511                                                    NTCREATEX_DISP_OVERWRITE, 0, 0);
3512
3513                         if (fnum1 == -1) {
3514                                 for (l = 0; l < ARRAY_SIZE(attr_results); l++) {
3515                                         if (attr_results[l].num == k) {
3516                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
3517                                                                 k, open_attrs_table[i],
3518                                                                 open_attrs_table[j],
3519                                                                 fname, NT_STATUS_V(cli_nt_error(cli1->tree)), cli_errstr(cli1->tree));
3520                                                 correct = False;
3521                                                 CHECK_MAX_FAILURES(error_exit);
3522                                         }
3523                                 }
3524                                 if (NT_STATUS_V(cli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) {
3525                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
3526                                                         k, open_attrs_table[i], open_attrs_table[j],
3527                                                         cli_errstr(cli1->tree));
3528                                         correct = False;
3529                                         CHECK_MAX_FAILURES(error_exit);
3530                                 }
3531 #if 0
3532                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
3533 #endif
3534                                 k++;
3535                                 continue;
3536                         }
3537
3538                         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3539                                 printf("close %d (2) of %s failed (%s)\n", j, fname, cli_errstr(cli1->tree));
3540                                 return False;
3541                         }
3542
3543                         if (NT_STATUS_IS_ERR(cli_getatr(cli1->tree, fname, &attr, NULL, NULL))) {
3544                                 printf("getatr(2) failed (%s)\n", cli_errstr(cli1->tree));
3545                                 return False;
3546                         }
3547
3548 #if 0
3549                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
3550                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
3551 #endif
3552
3553                         for (l = 0; l < ARRAY_SIZE(attr_results); l++) {
3554                                 if (attr_results[l].num == k) {
3555                                         if (attr != attr_results[l].result_attr ||
3556                                                         open_attrs_table[i] != attr_results[l].init_attr ||
3557                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
3558                                                 printf("[%d] getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
3559                                                         k, open_attrs_table[i],
3560                                                         open_attrs_table[j],
3561                                                         (uint_t)attr,
3562                                                         attr_results[l].result_attr);
3563                                                 correct = False;
3564                                                 CHECK_MAX_FAILURES(error_exit);
3565                                         }
3566                                         break;
3567                                 }
3568                         }
3569                         k++;
3570                 }
3571         }
3572 error_exit:
3573         cli_setatr(cli1->tree, fname, 0, 0);
3574         cli_unlink(cli1->tree, fname);
3575
3576         printf("open attr test %s.\n", correct ? "passed" : "failed");
3577
3578         if (!torture_close_connection(cli1)) {
3579                 correct = False;
3580         }
3581         return correct;
3582 }
3583
3584 static void list_fn(file_info *finfo, const char *name, void *state)
3585 {
3586         
3587 }
3588
3589 /*
3590   test directory listing speed
3591  */
3592 static BOOL run_dirtest(int dummy)
3593 {
3594         int i;
3595         struct cli_state *cli;
3596         int fnum;
3597         double t1;
3598         BOOL correct = True;
3599
3600         printf("starting directory test\n");
3601
3602         if (!torture_open_connection(&cli)) {
3603                 return False;
3604         }
3605
3606         printf("Creating %d random filenames\n", torture_numops);
3607
3608         srandom(0);
3609         for (i=0;i<torture_numops;i++) {
3610                 char *fname;
3611                 asprintf(&fname, "\\%x", (int)random());
3612                 fnum = cli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
3613                 if (fnum == -1) {
3614                         fprintf(stderr,"Failed to open %s\n", fname);
3615                         return False;
3616                 }
3617                 cli_close(cli->tree, fnum);
3618                 free(fname);
3619         }
3620
3621         t1 = end_timer();
3622
3623         printf("Matched %d\n", cli_list(cli->tree, "a*.*", 0, list_fn, NULL));
3624         printf("Matched %d\n", cli_list(cli->tree, "b*.*", 0, list_fn, NULL));
3625         printf("Matched %d\n", cli_list(cli->tree, "xyzabc", 0, list_fn, NULL));
3626
3627         printf("dirtest core %g seconds\n", end_timer() - t1);
3628
3629         srandom(0);
3630         for (i=0;i<torture_numops;i++) {
3631                 char *fname;
3632                 asprintf(&fname, "\\%x", (int)random());
3633                 cli_unlink(cli->tree, fname);
3634                 free(fname);
3635         }
3636
3637         if (!torture_close_connection(cli)) {
3638                 correct = False;
3639         }
3640
3641         printf("finished dirtest\n");
3642
3643         return correct;
3644 }
3645
3646 static void del_fn(file_info *finfo, const char *mask, void *state)
3647 {
3648         struct cli_state *pcli = (struct cli_state *)state;
3649         char *fname;
3650         asprintf(&fname, "\\LISTDIR\\%s", finfo->name);
3651
3652         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
3653                 return;
3654
3655         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
3656                 if (NT_STATUS_IS_ERR(cli_rmdir(pcli->tree, fname)))
3657                         printf("del_fn: failed to rmdir %s, error=%s\n", fname, cli_errstr(pcli->tree) );
3658         } else {
3659                 if (NT_STATUS_IS_ERR(cli_unlink(pcli->tree, fname)))
3660                         printf("del_fn: failed to unlink %s, error=%s\n", fname, cli_errstr(pcli->tree) );
3661         }
3662         free(fname);
3663 }
3664
3665
3666 /*
3667   sees what IOCTLs are supported
3668  */
3669 BOOL torture_ioctl_test(int dummy)
3670 {
3671         struct cli_state *cli;
3672         uint16_t device, function;
3673         int fnum;
3674         const char *fname = "\\ioctl.dat";
3675         NTSTATUS status;
3676         union smb_ioctl parms;
3677         TALLOC_CTX *mem_ctx;
3678
3679         if (!torture_open_connection(&cli)) {
3680                 return False;
3681         }
3682
3683         mem_ctx = talloc_init("ioctl_test");
3684
3685         printf("starting ioctl test\n");
3686
3687         cli_unlink(cli->tree, fname);
3688
3689         fnum = cli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
3690         if (fnum == -1) {
3691                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli->tree));
3692                 return False;
3693         }
3694
3695         parms.ioctl.level = RAW_IOCTL_IOCTL;
3696         parms.ioctl.in.request = IOCTL_QUERY_JOB_INFO;
3697         status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
3698         printf("ioctl job info: %s\n", cli_errstr(cli->tree));
3699
3700         for (device=0;device<0x100;device++) {
3701                 printf("testing device=0x%x\n", device);
3702                 for (function=0;function<0x100;function++) {
3703                         parms.ioctl.in.request = (device << 16) | function;
3704                         status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
3705
3706                         if (NT_STATUS_IS_OK(status)) {
3707                                 printf("ioctl device=0x%x function=0x%x OK : %d bytes\n", 
3708                                         device, function, parms.ioctl.out.blob.length);
3709                         }
3710                 }
3711         }
3712
3713         if (!torture_close_connection(cli)) {
3714                 return False;
3715         }
3716
3717         return True;
3718 }
3719
3720
3721 /*
3722   tries variants of chkpath
3723  */
3724 BOOL torture_chkpath_test(int dummy)
3725 {
3726         struct cli_state *cli;
3727         int fnum;
3728         BOOL ret;
3729
3730         if (!torture_open_connection(&cli)) {
3731                 return False;
3732         }
3733
3734         printf("starting chkpath test\n");
3735
3736         printf("Testing valid and invalid paths\n");
3737
3738         /* cleanup from an old run */
3739         cli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
3740         cli_unlink(cli->tree, "\\chkpath.dir\\*");
3741         cli_rmdir(cli->tree, "\\chkpath.dir");
3742
3743         if (NT_STATUS_IS_ERR(cli_mkdir(cli->tree, "\\chkpath.dir"))) {
3744                 printf("mkdir1 failed : %s\n", cli_errstr(cli->tree));
3745                 return False;
3746         }
3747
3748         if (NT_STATUS_IS_ERR(cli_mkdir(cli->tree, "\\chkpath.dir\\dir2"))) {
3749                 printf("mkdir2 failed : %s\n", cli_errstr(cli->tree));
3750                 return False;
3751         }
3752
3753         fnum = cli_open(cli->tree, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
3754         if (fnum == -1) {
3755                 printf("open1 failed (%s)\n", cli_errstr(cli->tree));
3756                 return False;
3757         }
3758         cli_close(cli->tree, fnum);
3759
3760         if (NT_STATUS_IS_ERR(cli_chkpath(cli->tree, "\\chkpath.dir"))) {
3761                 printf("chkpath1 failed: %s\n", cli_errstr(cli->tree));
3762                 ret = False;
3763         }
3764
3765         if (NT_STATUS_IS_ERR(cli_chkpath(cli->tree, "\\chkpath.dir\\dir2"))) {
3766                 printf("chkpath2 failed: %s\n", cli_errstr(cli->tree));
3767                 ret = False;
3768         }
3769
3770         if (NT_STATUS_IS_ERR(cli_chkpath(cli->tree, "\\chkpath.dir\\foo.txt"))) {
3771                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath, 
3772                                   NT_STATUS_NOT_A_DIRECTORY);
3773         } else {
3774                 printf("* chkpath on a file should fail\n");
3775                 ret = False;
3776         }
3777
3778         if (NT_STATUS_IS_ERR(cli_chkpath(cli->tree, "\\chkpath.dir\\bar.txt"))) {
3779                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadfile, 
3780                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
3781         } else {
3782                 printf("* chkpath on a non existent file should fail\n");
3783                 ret = False;
3784         }
3785
3786         if (NT_STATUS_IS_ERR(cli_chkpath(cli->tree, "\\chkpath.dir\\dirxx\\bar.txt"))) {
3787                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath, 
3788                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
3789         } else {
3790                 printf("* chkpath on a non existent component should fail\n");
3791                 ret = False;
3792         }
3793
3794         cli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
3795         cli_unlink(cli->tree, "\\chkpath.dir\\*");
3796         cli_rmdir(cli->tree, "\\chkpath.dir");
3797
3798         if (!torture_close_connection(cli)) {
3799                 return False;
3800         }
3801
3802         return ret;
3803 }
3804
3805 static BOOL run_dirtest1(int dummy)
3806 {
3807         int i;
3808         struct cli_state *cli;
3809         int fnum, num_seen;
3810         BOOL correct = True;
3811
3812         printf("starting directory test\n");
3813
3814         if (!torture_open_connection(&cli)) {
3815                 return False;
3816         }
3817
3818         cli_list(cli->tree, "\\LISTDIR\\*", 0, del_fn, cli);
3819         cli_list(cli->tree, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
3820         if (cli_deltree(cli->tree, "\\LISTDIR") == -1) {
3821                 fprintf(stderr,"Failed to deltree %s, error=%s\n", "\\LISTDIR", cli_errstr(cli->tree));
3822                 return False;
3823         }
3824         if (NT_STATUS_IS_ERR(cli_mkdir(cli->tree, "\\LISTDIR"))) {
3825                 fprintf(stderr,"Failed to mkdir %s, error=%s\n", "\\LISTDIR", cli_errstr(cli->tree));
3826                 return False;
3827         }
3828
3829         printf("Creating %d files\n", torture_entries);
3830
3831         /* Create torture_entries files and torture_entries directories. */
3832         for (i=0;i<torture_entries;i++) {
3833                 char *fname;
3834                 asprintf(&fname, "\\LISTDIR\\f%d", i);
3835                 fnum = cli_nt_create_full(cli->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
3836                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3837                 if (fnum == -1) {
3838                         fprintf(stderr,"Failed to open %s, error=%s\n", fname, cli_errstr(cli->tree));
3839                         return False;
3840                 }
3841                 free(fname);
3842                 cli_close(cli->tree, fnum);
3843         }
3844         for (i=0;i<torture_entries;i++) {
3845                 char *fname;
3846                 asprintf(&fname, "\\LISTDIR\\d%d", i);
3847                 if (NT_STATUS_IS_ERR(cli_mkdir(cli->tree, fname))) {
3848                         fprintf(stderr,"Failed to open %s, error=%s\n", fname, cli_errstr(cli->tree));
3849                         return False;
3850                 }
3851                 free(fname);
3852         }
3853
3854         /* Now ensure that doing an old list sees both files and directories. */
3855         num_seen = cli_list_old(cli->tree, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, NULL);
3856         printf("num_seen = %d\n", num_seen );
3857         /* We should see (torture_entries) each of files & directories + . and .. */
3858         if (num_seen != (2*torture_entries)+2) {
3859                 correct = False;
3860                 fprintf(stderr,"entry count mismatch, should be %d, was %d\n",
3861                         (2*torture_entries)+2, num_seen);
3862         }
3863                 
3864
3865         /* Ensure if we have the "must have" bits we only see the
3866          * relevant entries.
3867          */
3868         num_seen = cli_list_old(cli->tree, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, NULL);
3869         printf("num_seen = %d\n", num_seen );
3870         if (num_seen != torture_entries+2) {
3871                 correct = False;
3872                 fprintf(stderr,"entry count mismatch, should be %d, was %d\n",
3873                         torture_entries+2, num_seen);
3874         }
3875
3876         num_seen = cli_list_old(cli->tree, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, NULL);
3877         printf("num_seen = %d\n", num_seen );
3878         if (num_seen != torture_entries) {
3879                 correct = False;
3880                 fprintf(stderr,"entry count mismatch, should be %d, was %d\n",
3881                         torture_entries, num_seen);
3882         }
3883
3884         /* Delete everything. */
3885         cli_list(cli->tree, "\\LISTDIR\\*", 0, del_fn, cli);
3886         cli_list(cli->tree, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
3887         cli_rmdir(cli->tree, "\\LISTDIR");
3888
3889 #if 0
3890         printf("Matched %d\n", cli_list(cli->tree, "a*.*", 0, list_fn, NULL));
3891         printf("Matched %d\n", cli_list(cli->tree, "b*.*", 0, list_fn, NULL));
3892         printf("Matched %d\n", cli_list(cli->tree, "xyzabc", 0, list_fn, NULL));
3893 #endif
3894
3895         if (!torture_close_connection(cli)) {
3896                 correct = False;
3897         }
3898
3899         printf("finished dirtest1\n");
3900
3901         return correct;
3902 }
3903
3904
3905 /*
3906    simple test harness for playing with deny modes
3907  */
3908 static BOOL run_deny3test(int dummy)
3909 {
3910         struct cli_state *cli1, *cli2;
3911         int fnum1, fnum2;
3912         const char *fname;
3913
3914         printf("starting deny3 test\n");
3915
3916         printf("Testing simple deny modes\n");
3917         
3918         if (!torture_open_connection(&cli1)) {
3919                 return False;
3920         }
3921         if (!torture_open_connection(&cli2)) {
3922                 return False;
3923         }
3924
3925         fname = "\\deny_dos1.dat";
3926
3927         cli_unlink(cli1->tree, fname);
3928         fnum1 = cli_open(cli1->tree, fname, O_CREAT|O_TRUNC|O_WRONLY, DENY_DOS);
3929         fnum2 = cli_open(cli1->tree, fname, O_CREAT|O_TRUNC|O_WRONLY, DENY_DOS);
3930         if (fnum1 != -1) cli_close(cli1->tree, fnum1);
3931         if (fnum2 != -1) cli_close(cli1->tree, fnum2);
3932         cli_unlink(cli1->tree, fname);
3933         printf("fnum1=%d fnum2=%d\n", fnum1, fnum2);
3934
3935
3936         fname = "\\deny_dos2.dat";
3937
3938         cli_unlink(cli1->tree, fname);
3939         fnum1 = cli_open(cli1->tree, fname, O_CREAT|O_TRUNC|O_WRONLY, DENY_DOS);
3940         fnum2 = cli_open(cli2->tree, fname, O_CREAT|O_TRUNC|O_WRONLY, DENY_DOS);
3941         if (fnum1 != -1) cli_close(cli1->tree, fnum1);
3942         if (fnum2 != -1) cli_close(cli2->tree, fnum2);
3943         cli_unlink(cli1->tree, fname);
3944         printf("fnum1=%d fnum2=%d\n", fnum1, fnum2);
3945
3946
3947         torture_close_connection(cli1);
3948         torture_close_connection(cli2);
3949
3950         return True;
3951 }
3952
3953 /*
3954   parse a //server/share type UNC name
3955 */
3956 static BOOL parse_unc(const char *unc_name, char **hostname, char **sharename)
3957 {
3958         char *p;
3959
3960         if (strncmp(unc_name, "//", 2)) {
3961                 return False;
3962         }
3963
3964         *hostname = strdup(&unc_name[2]);
3965         p = strchr_m(&(*hostname)[2],'/');
3966         if (!p) {
3967                 return False;
3968         }
3969         *p = 0;
3970         *sharename = strdup(p+1);
3971
3972         return True;
3973 }
3974
3975
3976
3977 static void sigcont(void)
3978 {
3979 }
3980
3981 double torture_create_procs(BOOL (*fn)(struct cli_state *, int), BOOL *result)
3982 {
3983         int i, status;
3984         volatile pid_t *child_status;
3985         volatile BOOL *child_status_out;
3986         int synccount;
3987         int tries = 8;
3988         double start_time_limit = 10 + (torture_nprocs * 1.5);
3989         char **unc_list = NULL;
3990         const char *p;
3991         int num_unc_names = 0;
3992
3993         synccount = 0;
3994
3995         signal(SIGCONT, sigcont);
3996
3997         child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*torture_nprocs);
3998         if (!child_status) {
3999                 printf("Failed to setup shared memory\n");
4000                 return -1;
4001         }
4002
4003         child_status_out = (volatile BOOL *)shm_setup(sizeof(BOOL)*torture_nprocs);
4004         if (!child_status_out) {
4005                 printf("Failed to setup result status shared memory\n");
4006                 return -1;
4007         }
4008
4009         p = lp_parm_string(-1, "torture", "unclist");
4010         if (p) {
4011                 unc_list = file_lines_load(p, &num_unc_names);
4012                 if (!unc_list || num_unc_names <= 0) {
4013                         printf("Failed to load unc names list from %s\n", p);
4014                         exit(1);
4015                 }
4016         }
4017
4018         for (i = 0; i < torture_nprocs; i++) {
4019                 child_status[i] = 0;
4020                 child_status_out[i] = True;
4021         }
4022
4023         start_timer();
4024
4025         for (i=0;i<torture_nprocs;i++) {
4026                 procnum = i;
4027                 if (fork() == 0) {
4028                         char *myname;
4029                         char *hostname=NULL, *sharename;
4030
4031                         pid_t mypid = getpid();
4032                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
4033
4034                         asprintf(&myname, "CLIENT%d", i);
4035                         lp_set_cmdline("netbios name", myname);
4036                         free(myname);
4037
4038
4039                         if (unc_list) {
4040                                 if (!parse_unc(unc_list[i % num_unc_names],
4041                                                &hostname, &sharename)) {
4042                                         printf("Failed to parse UNC name %s\n",
4043                                                unc_list[i % num_unc_names]);
4044                                         exit(1);
4045                                 }
4046                         }
4047
4048                         while (1) {
4049                                 if (hostname) {
4050                                         if (torture_open_connection_share(&current_cli,
4051                                                                           hostname, 
4052                                                                           sharename)) {
4053                                                 break;
4054                                         }
4055                                 } else if (torture_open_connection(&current_cli)) {
4056                                                 break;
4057                                 }
4058                                 if (tries-- == 0) {
4059                                         printf("pid %d failed to start\n", (int)getpid());
4060                                         _exit(1);
4061                                 }
4062                                 msleep(100);    
4063                         }
4064
4065                         child_status[i] = getpid();
4066
4067                         pause();
4068
4069                         if (child_status[i]) {
4070                                 printf("Child %d failed to start!\n", i);
4071                                 child_status_out[i] = 1;
4072                                 _exit(1);
4073                         }
4074
4075                         child_status_out[i] = fn(current_cli, i);
4076                         _exit(0);
4077                 }
4078         }
4079
4080         do {
4081                 synccount = 0;
4082                 for (i=0;i<torture_nprocs;i++) {
4083                         if (child_status[i]) synccount++;
4084                 }
4085                 if (synccount == torture_nprocs) break;
4086                 msleep(100);
4087         } while (end_timer() < start_time_limit);
4088
4089         if (synccount != torture_nprocs) {
4090                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
4091                 *result = False;
4092                 return end_timer();
4093         }
4094
4095         printf("Starting %d clients\n", torture_nprocs);
4096
4097         /* start the client load */
4098         start_timer();
4099         for (i=0;i<torture_nprocs;i++) {
4100                 child_status[i] = 0;
4101         }
4102         kill(0, SIGCONT);
4103
4104         printf("%d clients started\n", torture_nprocs);
4105
4106         for (i=0;i<torture_nprocs;i++) {
4107                 int ret;
4108                 while ((ret=waitpid(0, &status, 0)) == -1 && errno == EINTR) /* noop */ ;
4109                 if (ret == -1 || WEXITSTATUS(status) != 0) {
4110                         *result = False;
4111                 }
4112         }
4113
4114         printf("\n");
4115         
4116         for (i=0;i<torture_nprocs;i++) {
4117                 if (!child_status_out[i]) {
4118                         *result = False;
4119                 }
4120         }
4121         return end_timer();
4122 }
4123
4124 #define FLAG_MULTIPROC 1
4125
4126 static struct {
4127         const char *name;
4128         BOOL (*fn)(int);
4129         uint_t flags;
4130 } torture_ops[] = {
4131         {"FDPASS", run_fdpasstest, 0},
4132         {"LOCK1",  run_locktest1,  0},
4133         {"LOCK2",  run_locktest2,  0},
4134         {"LOCK3",  run_locktest3,  0},
4135         {"LOCK4",  run_locktest4,  0},
4136         {"LOCK5",  run_locktest5,  0},
4137         {"LOCK6",  run_locktest6,  0},
4138         {"LOCK7",  run_locktest7,  0},
4139         {"UNLINK", run_unlinktest, 0},
4140         {"ATTR",   run_attrtest,   0},
4141         {"TRANS2", run_trans2test, 0},
4142         {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
4143         {"TORTURE",run_torture,    FLAG_MULTIPROC},
4144         {"NEGNOWAIT", run_negprot_nowait, 0},
4145         {"NBENCH",  torture_nbench, 0},
4146         {"DIR",  run_dirtest, 0},
4147         {"DIR1",  run_dirtest1, 0},
4148         {"DENY1",  torture_denytest1, 0},
4149         {"DENY2",  torture_denytest2, 0},
4150         {"TCON",  run_tcon_test, 0},
4151         {"TCONDEV",  run_tcon_devtype_test, 0},
4152         {"VUID", run_vuidtest, 0},
4153 #if 0
4154         {"DFSBASIC", torture_dfs_basic, 0},
4155         {"DFSRENAME", torture_dfs_rename, 0},
4156         {"DFSRANDOM", torture_dfs_random, 0},
4157 #endif
4158         {"RW1",  run_readwritetest, 0},
4159         {"RW2",  run_readwritemulti, FLAG_MULTIPROC},
4160         {"OPEN", run_opentest, 0},
4161         {"DENY3", run_deny3test, 0},
4162 #if 1
4163         {"OPENATTR", run_openattrtest, 0},
4164 #endif
4165         {"DEFER_OPEN", run_deferopen, FLAG_MULTIPROC},
4166         {"XCOPY", run_xcopy, 0},
4167         {"RENAME", run_rename, 0},
4168         {"DELETE", run_deletetest, 0},
4169         {"PROPERTIES", run_properties, 0},
4170         {"MANGLE", torture_mangle, 0},
4171         {"UTABLE", torture_utable, 0},
4172         {"CASETABLE", torture_casetable, 0},
4173         {"CHARSET", torture_charset, 0},
4174         {"PIPE_NUMBER", run_pipe_number, 0},
4175         {"IOCTL",  torture_ioctl_test, 0},
4176         {"CHKPATH",  torture_chkpath_test, 0},
4177         {"HOLDCON",  torture_holdcon, 0},
4178         {"RAW-QFSINFO", torture_raw_qfsinfo, 0},
4179         {"RAW-QFILEINFO", torture_raw_qfileinfo, 0},
4180         {"RAW-SFILEINFO", torture_raw_sfileinfo, 0},
4181         {"RAW-SFILEINFO-BUG", torture_raw_sfileinfo_bug, 0},
4182         {"RAW-SEARCH", torture_raw_search, 0},
4183         {"RAW-CLOSE", torture_raw_close, 0},
4184         {"RAW-OPEN", torture_raw_open, 0},
4185         {"RAW-MKDIR", torture_raw_mkdir, 0},
4186         {"RAW-OPLOCK", torture_raw_oplock, 0},
4187         {"RAW-NOTIFY", torture_raw_notify, 0},
4188         {"RAW-MUX", torture_raw_mux, 0},
4189         {"RAW-IOCTL", torture_raw_ioctl, 0},
4190         {"RAW-CHKPATH", torture_raw_chkpath, 0},
4191         {"RAW-UNLINK", torture_raw_unlink, 0},
4192         {"RAW-READ", torture_raw_read, 0},
4193         {"RAW-WRITE", torture_raw_write, 0},
4194         {"RAW-LOCK", torture_raw_lock, 0},
4195         {"RAW-CONTEXT", torture_raw_context, 0},
4196         {"RAW-RENAME", torture_raw_rename, 0},
4197         {"RAW-SEEK", torture_raw_seek, 0},
4198         {"RAW-RAP", torture_raw_rap, 0},
4199         {"SCAN-TRANS2", torture_trans2_scan, 0},
4200         {"SCAN-NTTRANS", torture_nttrans_scan, 0},
4201         {"SCAN-ALIASES", torture_trans2_aliases, 0},
4202         {"SCAN-SMB", torture_smb_scan, 0},
4203         {"RPC-LSA", torture_rpc_lsa, 0},
4204         {"RPC-ECHO", torture_rpc_echo, 0},
4205         {"RPC-DFS", torture_rpc_dfs, 0},
4206         {"RPC-SPOOLSS", torture_rpc_spoolss, 0},
4207         {"RPC-SAMR", torture_rpc_samr, 0},
4208         {"RPC-NETLOGON", torture_rpc_netlogon, 0},
4209         {"RPC-SCHANNEL", torture_rpc_schannel, 0},
4210         {"RPC-WKSSVC", torture_rpc_wkssvc, 0},
4211         {"RPC-SRVSVC", torture_rpc_srvsvc, 0},
4212         {"RPC-ATSVC", torture_rpc_atsvc, 0},
4213         {"RPC-EVENTLOG", torture_rpc_eventlog, 0},
4214         {"RPC-EPMAPPER", torture_rpc_epmapper, 0},
4215         {"RPC-WINREG", torture_rpc_winreg, 0},
4216         {"RPC-MGMT", torture_rpc_mgmt, 0},
4217         {"RPC-SCANNER", torture_rpc_scanner, 0},
4218         {"RPC-AUTOIDL", torture_rpc_autoidl, 0},
4219         {"RPC-MULTIBIND", torture_multi_bind, 0},
4220         {"RPC-DRSUAPI", torture_rpc_drsuapi, 0},
4221         {"NTLMSSP-SELFCHECK", torture_ntlmssp_self_check, 0},
4222         {NULL, NULL, 0}};
4223
4224
4225
4226 /****************************************************************************
4227 run a specified test or "ALL"
4228 ****************************************************************************/
4229 static BOOL run_test(const char *name)
4230 {
4231         BOOL ret = True;
4232         int i;
4233         BOOL matched = False;
4234
4235         if (strequal(name,"ALL")) {
4236                 for (i=0;torture_ops[i].name;i++) {
4237                         if (!run_test(torture_ops[i].name)) {
4238                                 ret = False;
4239                         }
4240                 }
4241                 return ret;
4242         }
4243
4244         for (i=0;torture_ops[i].name;i++) {
4245                 if (gen_fnmatch(name, torture_ops[i].name) == 0) {
4246                         double t;
4247                         matched = True;
4248                         printf("Running %s\n", torture_ops[i].name);
4249                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
4250                                 BOOL result;
4251                                 t = torture_create_procs(torture_ops[i].fn, &result);
4252                                 if (!result) { 
4253                                         ret = False;
4254                                         printf("TEST %s FAILED!\n", torture_ops[i].name);
4255                                 }
4256                                          
4257                         } else {
4258                                 start_timer();
4259                                 if (!torture_ops[i].fn(0)) {
4260                                         ret = False;
4261                                         printf("TEST %s FAILED!\n", torture_ops[i].name);
4262                                 }
4263                                 t = end_timer();
4264                         }
4265                         printf("%s took %g secs\n\n", torture_ops[i].name, t);
4266                 }
4267         }
4268
4269         if (!matched) {
4270                 printf("Unknown torture operation '%s'\n", name);
4271         }
4272
4273         return ret;
4274 }
4275
4276
4277 /*
4278   parse a username%password
4279 */
4280 static void parse_user(const char *user)
4281 {
4282         char *username, *password = NULL, *p;
4283
4284         username = strdup(user);
4285         p = strchr_m(username,'%');
4286         if (p) {
4287                 *p = 0;
4288                 password = strdup(p+1);
4289         }
4290
4291         lp_set_cmdline("torture:username", username);
4292
4293         if (password) {
4294                 lp_set_cmdline("torture:password", password);
4295         }
4296
4297         if (!lp_parm_string(-1,"torture","password")) {
4298                 password = getpass("password:");
4299
4300                 lp_set_cmdline("torture:password", password);
4301         }
4302 }
4303
4304 static void usage(void)
4305 {
4306         int i;
4307
4308         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
4309
4310         printf("\t-d debuglevel\n");
4311         printf("\t-U user%%pass\n");
4312         printf("\t-k use kerberos\n");
4313         printf("\t-N numprocs\n");
4314         printf("\t-n my_netbios_name\n");
4315         printf("\t-W workgroup\n");
4316         printf("\t-o num_operations\n");
4317         printf("\t-e num files(entries)\n");
4318         printf("\t-O socket_options\n");
4319         printf("\t-m maximum protocol\n");
4320         printf("\t-L use oplocks\n");
4321         printf("\t-c CLIENT.TXT   specify client load file for NBENCH\n");
4322         printf("\t-t timelimit    specify NBENCH time limit (seconds)\n");
4323         printf("\t-C filename     specifies file with list of UNCs for connections\n");
4324         printf("\t-A showall\n");
4325         printf("\t-p port\n");
4326         printf("\t-s seed\n");
4327         printf("\t-f max failures\n");
4328         printf("\t-X enable dangerous tests\n");
4329         printf("\n\n");
4330
4331         printf("tests are:");
4332         for (i=0;torture_ops[i].name;i++) {
4333                 printf(" %s", torture_ops[i].name);
4334         }
4335         printf("\n");
4336
4337         printf("default test is ALL\n");
4338         
4339         exit(1);
4340 }
4341
4342 /****************************************************************************
4343   main program
4344 ****************************************************************************/
4345  int main(int argc,char *argv[])
4346 {
4347         int opt, i;
4348         char *p;
4349         BOOL correct = True;
4350         char *host, *share, *username;
4351
4352         setup_logging("smbtorture", DEBUG_STDOUT);
4353
4354 #ifdef HAVE_SETBUFFER
4355         setbuffer(stdout, NULL, 0);
4356 #endif
4357
4358         lp_load(dyn_CONFIGFILE,True,False,False);
4359         load_interfaces();
4360
4361         if (argc < 2) {
4362                 usage();
4363         }
4364
4365         for(p = argv[1]; *p; p++)
4366           if(*p == '\\')
4367             *p = '/';
4368
4369
4370         /* see if its a RPC transport specifier */
4371         if (strncmp(argv[1], "ncacn_", 6) == 0) {
4372                 lp_set_cmdline("torture:binding", argv[1]);
4373         } else {
4374                 char *binding = NULL;
4375
4376                 if (!parse_unc(argv[1], &host, &share)) {
4377                         usage();
4378                 }
4379
4380                 lp_set_cmdline("torture:host", host);
4381                 lp_set_cmdline("torture:share", share);
4382                 asprintf(&binding, "ncacn_np:%s", host);
4383                 lp_set_cmdline("torture:binding", binding);
4384         }
4385
4386         if (getenv("LOGNAME")) {
4387                 username = strdup(getenv("LOGNAME"));
4388         }
4389         lp_set_cmdline("torture:username", username);
4390
4391
4392         argc--;
4393         argv++;
4394
4395         srandom(time(NULL));
4396
4397         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:e:m:Ld:Ac:ks:f:s:t:C:X")) != EOF) {
4398                 switch (opt) {
4399                 case 'p':
4400                         lp_set_cmdline("smb ports", optarg);
4401                         break;
4402                 case 'W':
4403                         lp_set_cmdline("workgroup", optarg);
4404                         break;
4405                 case 'm':
4406                         lp_set_cmdline("protocol", optarg);
4407                         break;
4408                 case 'n':
4409                         lp_set_cmdline("netbios name", optarg);
4410                         break;
4411                 case 'd':
4412                         lp_set_cmdline("debug level", optarg);
4413                         setup_logging(NULL, DEBUG_STDOUT);
4414                         break;
4415                 case 'O':
4416                         lp_set_cmdline("socket options", optarg);
4417                         break;
4418                 case 's':
4419                         srandom(atoi(optarg));
4420                         break;
4421                 case 'N':
4422                         torture_nprocs = atoi(optarg);
4423                         break;
4424                 case 'o':
4425                         torture_numops = atoi(optarg);
4426                         break;
4427                 case 'e':
4428                         torture_entries = atoi(optarg);
4429                         break;
4430                 case 'L':
4431                         use_oplocks = True;
4432                         break;
4433                 case 'A':
4434                         torture_showall = True;
4435                         break;
4436                 case 'c':
4437                         lp_set_cmdline("torture:loadfile", optarg);
4438                         break;
4439                 case 'C':
4440                         lp_set_cmdline("torture:unclist", optarg);
4441                         break;
4442                 case 't':
4443                         lp_set_cmdline("torture:timelimit", optarg);
4444                         break;
4445                 case 'k':
4446 #ifdef HAVE_KRB5
4447                         use_kerberos = True;
4448 #else
4449                         d_printf("No kerberos support compiled in\n");
4450                         exit(1);
4451 #endif
4452                         break;
4453                 case 'U':
4454                         parse_user(optarg);
4455                         break;
4456                 case 'f':
4457                         torture_failures = atoi(optarg);
4458                         break;
4459
4460                 case 'X':
4461                         lp_set_cmdline("torture:dangerous", "1");
4462                         break;
4463
4464                 default:
4465                         printf("Unknown option %c (%d)\n", (char)opt, opt);
4466                         usage();
4467                 }
4468         }
4469
4470         if (!lp_parm_string(-1,"torture","password")) {
4471                 lp_set_cmdline("torture:password", "");
4472         }
4473
4474         if (argc == optind) {
4475                 printf("You must specify a test to run, or 'ALL'\n");
4476         } else {
4477                 for (i=optind;i<argc;i++) {
4478                         if (!run_test(argv[i])) {
4479                                 correct = False;
4480                         }
4481                 }
4482         }
4483
4484         if (correct) {
4485                 return(0);
4486         } else {
4487                 return(1);
4488         }
4489 }