Convert libcli routines to return NTSTATUS instead of BOOL. Again, the
[samba.git] / source4 / torture / torture.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-2003
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 static int 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 const char *client_txt = "client_oplocks.txt";
32 static BOOL use_kerberos;
33
34 BOOL torture_showall = False;
35
36 static double create_procs(BOOL (*fn)(int), BOOL *result);
37
38 #define CHECK_MAX_FAILURES(label) do { if (++failures >= torture_failures) goto label; } while (0)
39
40 static struct cli_state *open_nbt_connection(void)
41 {
42         struct nmb_name called, calling;
43         struct in_addr ip;
44         struct cli_state *cli;
45         char *host = lp_parm_string(-1, "torture", "host");
46
47         make_nmb_name(&calling, lp_netbios_name(), 0x0);
48         make_nmb_name(&called , host, 0x20);
49
50         zero_ip(&ip);
51
52         cli = cli_state_init();
53         if (!cli) {
54                 printf("Failed initialize cli_struct to connect with %s\n", host);
55                 return NULL;
56         }
57
58         if (!cli_socket_connect(cli, host, &ip)) {
59                 printf("Failed to connect with %s\n", host);
60                 return cli;
61         }
62
63         cli->transport->socket->timeout = 120000; /* set a really long timeout (2 minutes) */
64
65         if (!cli_transport_establish(cli, &calling, &called)) {
66                 /*
67                  * Well, that failed, try *SMBSERVER ... 
68                  * However, we must reconnect as well ...
69                  */
70                 if (!cli_socket_connect(cli, host, &ip)) {
71                         printf("Failed to connect with %s\n", host);
72                         return False;
73                 }
74
75                 make_nmb_name(&called, "*SMBSERVER", 0x20);
76                 if (!cli_transport_establish(cli, &calling, &called)) {
77                         printf("%s rejected the session\n",host);
78                         printf("We tried with a called name of %s & %s\n",
79                                 host, "*SMBSERVER");
80                         cli_shutdown(cli);
81                         return NULL;
82                 }
83         }
84
85         return cli;
86 }
87
88 BOOL torture_open_connection(struct cli_state **c)
89 {
90         BOOL retry;
91         int flags = 0;
92         NTSTATUS status;
93         char *host = lp_parm_string(-1, "torture", "host");
94         char *share = lp_parm_string(-1, "torture", "share");
95         char *username = lp_parm_string(-1, "torture", "username");
96         char *password = lp_parm_string(-1, "torture", "password");
97
98         if (use_kerberos)
99                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
100
101         status = cli_full_connection(c, lp_netbios_name(),
102                                      host, NULL, 
103                                      share, "?????", 
104                                      username, username[0]?lp_workgroup():"",
105                                      password, flags, &retry);
106         if (!NT_STATUS_IS_OK(status)) {
107                 printf("Failed to open connection - %s\n", nt_errstr(status));
108                 return False;
109         }
110
111         (*c)->transport->options.use_oplocks = use_oplocks;
112         (*c)->transport->options.use_level2_oplocks = use_level_II_oplocks;
113         (*c)->transport->socket->timeout = 120000;
114
115         return True;
116 }
117
118 BOOL torture_close_connection(struct cli_state *c)
119 {
120         BOOL ret = True;
121         DEBUG(9,("torture_close_connection: cli_state@%p\n", c));
122         if (!c) return True;
123         if (NT_STATUS_IS_ERR(cli_tdis(c))) {
124                 printf("tdis failed (%s)\n", cli_errstr(c->tree));
125                 ret = False;
126         }
127         DEBUG(9,("torture_close_connection: call cli_shutdown\n"));
128         cli_shutdown(c);
129         DEBUG(9,("torture_close_connection: exit\n"));
130         return ret;
131 }
132
133
134 /* open a rpc connection to a named pipe */
135 NTSTATUS torture_rpc_connection(struct dcerpc_pipe **p, 
136                                 const char *pipe_name,
137                                 const char *pipe_uuid, 
138                                 uint32 pipe_version)
139 {
140         NTSTATUS status;
141         char *binding = lp_parm_string(-1, "torture", "binding");
142
143         if (!binding) {
144                 printf("You must specify a ncacn binding string\n");
145                 return NT_STATUS_INVALID_PARAMETER;
146         }
147
148         status = dcerpc_pipe_connect(p, binding, pipe_uuid, pipe_version,
149                                      lp_workgroup(), 
150                                      lp_parm_string(-1, "torture", "username"),
151                                      lp_parm_string(-1, "torture", "password"));
152  
153         return status;
154 }
155
156 /* close a rpc connection to a named pipe */
157 NTSTATUS torture_rpc_close(struct dcerpc_pipe *p)
158 {
159         dcerpc_pipe_close(p);
160         return NT_STATUS_OK;
161 }
162
163
164 /* check if the server produced the expected error code */
165 static BOOL check_error(int line, struct cli_state *c, 
166                         uint8 eclass, uint32 ecode, NTSTATUS nterr)
167 {
168         if (cli_is_dos_error(c->tree)) {
169                 uint8 class;
170                 uint32 num;
171
172                 /* Check DOS error */
173
174                 cli_dos_error(c, &class, &num);
175
176                 if (eclass != class || ecode != num) {
177                         printf("unexpected error code class=%d code=%d\n", 
178                                (int)class, (int)num);
179                         printf(" expected %d/%d %s (line=%d)\n", 
180                                (int)eclass, (int)ecode, nt_errstr(nterr), line);
181                         return False;
182                 }
183
184         } else {
185                 NTSTATUS status;
186
187                 /* Check NT error */
188
189                 status = cli_nt_error(c->tree);
190
191                 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
192                         printf("unexpected error code %s\n", nt_errstr(status));
193                         printf(" expected %s (line=%d)\n", nt_errstr(nterr), line);
194                         return False;
195                 }
196         }
197
198         return True;
199 }
200
201
202 static BOOL wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
203 {
204         while (NT_STATUS_IS_ERR(cli_lock(c->tree, fnum, offset, len, -1, WRITE_LOCK))) {
205                 if (!check_error(__LINE__, c, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
206         }
207         return True;
208 }
209
210
211 static BOOL rw_torture(struct cli_state *c)
212 {
213         const char *lockfname = "\\torture.lck";
214         char *fname;
215         int fnum;
216         int fnum2;
217         pid_t pid2, pid = getpid();
218         int i, j;
219         char buf[1024];
220         BOOL correct = True;
221
222         fnum2 = cli_open(c->tree, lockfname, O_RDWR | O_CREAT | O_EXCL, 
223                          DENY_NONE);
224         if (fnum2 == -1)
225                 fnum2 = cli_open(c->tree, lockfname, O_RDWR, DENY_NONE);
226         if (fnum2 == -1) {
227                 printf("open of %s failed (%s)\n", lockfname, cli_errstr(c->tree));
228                 return False;
229         }
230
231
232         for (i=0;i<torture_numops;i++) {
233                 unsigned n = (unsigned)sys_random()%10;
234                 if (i % 10 == 0) {
235                         printf("%d\r", i); fflush(stdout);
236                 }
237                 asprintf(&fname, "\\torture.%u", n);
238
239                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
240                         return False;
241                 }
242
243                 fnum = cli_open(c->tree, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
244                 if (fnum == -1) {
245                         printf("open failed (%s)\n", cli_errstr(c->tree));
246                         correct = False;
247                         break;
248                 }
249
250                 if (cli_write(c->tree, fnum, 0, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
251                         printf("write failed (%s)\n", cli_errstr(c->tree));
252                         correct = False;
253                 }
254
255                 for (j=0;j<50;j++) {
256                         if (cli_write(c->tree, fnum, 0, (char *)buf, 
257                                       sizeof(pid)+(j*sizeof(buf)), 
258                                       sizeof(buf)) != sizeof(buf)) {
259                                 printf("write failed (%s)\n", cli_errstr(c->tree));
260                                 correct = False;
261                         }
262                 }
263
264                 pid2 = 0;
265
266                 if (cli_read(c->tree, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
267                         printf("read failed (%s)\n", cli_errstr(c->tree));
268                         correct = False;
269                 }
270
271                 if (pid2 != pid) {
272                         printf("data corruption!\n");
273                         correct = False;
274                 }
275
276                 if (NT_STATUS_IS_ERR(cli_close(c->tree, fnum))) {
277                         printf("close failed (%s)\n", cli_errstr(c->tree));
278                         correct = False;
279                 }
280
281                 if (NT_STATUS_IS_ERR(cli_unlink(c->tree, fname))) {
282                         printf("unlink failed (%s)\n", cli_errstr(c->tree));
283                         correct = False;
284                 }
285
286                 if (NT_STATUS_IS_ERR(cli_unlock(c->tree, fnum2, n*sizeof(int), sizeof(int)))) {
287                         printf("unlock failed (%s)\n", cli_errstr(c->tree));
288                         correct = False;
289                 }
290                 free(fname);
291         }
292
293         cli_close(c->tree, fnum2);
294         cli_unlink(c->tree, lockfname);
295
296         printf("%d\n", i);
297
298         return correct;
299 }
300
301 static BOOL run_torture(int dummy)
302 {
303         struct cli_state *cli;
304         BOOL ret;
305
306         cli = current_cli;
307
308         ret = rw_torture(cli);
309         
310         if (!torture_close_connection(cli)) {
311                 ret = False;
312         }
313
314         return ret;
315 }
316
317 static BOOL rw_torture3(struct cli_state *c, const char *lockfname)
318 {
319         int fnum = -1;
320         unsigned int i = 0;
321         char buf[131072];
322         char buf_rd[131072];
323         unsigned count;
324         unsigned countprev = 0;
325         ssize_t sent = 0;
326         BOOL correct = True;
327
328         srandom(1);
329         for (i = 0; i < sizeof(buf); i += sizeof(uint32))
330         {
331                 SIVAL(buf, i, sys_random());
332         }
333
334         if (procnum == 0)
335         {
336                 fnum = cli_open(c->tree, lockfname, O_RDWR | O_CREAT | O_EXCL, 
337                                 DENY_NONE);
338                 if (fnum == -1) {
339                         printf("first open read/write of %s failed (%s)\n",
340                                         lockfname, cli_errstr(c->tree));
341                         return False;
342                 }
343         }
344         else
345         {
346                 for (i = 0; i < 500 && fnum == -1; i++)
347                 {
348                         fnum = cli_open(c->tree, lockfname, O_RDONLY, 
349                                         DENY_NONE);
350                         msleep(10);
351                 }
352                 if (fnum == -1) {
353                         printf("second open read-only of %s failed (%s)\n",
354                                         lockfname, cli_errstr(c->tree));
355                         return False;
356                 }
357         }
358
359         i = 0;
360         for (count = 0; count < sizeof(buf); count += sent)
361         {
362                 if (count >= countprev) {
363                         printf("%d %8d\r", i, count);
364                         fflush(stdout);
365                         i++;
366                         countprev += (sizeof(buf) / 20);
367                 }
368
369                 if (procnum == 0)
370                 {
371                         sent = ((unsigned)sys_random()%(20))+ 1;
372                         if (sent > sizeof(buf) - count)
373                         {
374                                 sent = sizeof(buf) - count;
375                         }
376
377                         if (cli_write(c->tree, fnum, 0, buf+count, count, (size_t)sent) != sent) {
378                                 printf("write failed (%s)\n", cli_errstr(c->tree));
379                                 correct = False;
380                         }
381                 }
382                 else
383                 {
384                         sent = cli_read(c->tree, fnum, buf_rd+count, count,
385                                         sizeof(buf)-count);
386                         if (sent < 0)
387                         {
388                                 printf("read failed offset:%d size:%d (%s)\n",
389                                                 count, sizeof(buf)-count,
390                                                 cli_errstr(c->tree));
391                                 correct = False;
392                                 sent = 0;
393                         }
394                         if (sent > 0)
395                         {
396                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
397                                 {
398                                         printf("read/write compare failed\n");
399                                         printf("offset: %d req %d recvd %d\n",
400                                                 count, sizeof(buf)-count, sent);
401                                         correct = False;
402                                         break;
403                                 }
404                         }
405                 }
406
407         }
408
409         if (NT_STATUS_IS_ERR(cli_close(c->tree, fnum))) {
410                 printf("close failed (%s)\n", cli_errstr(c->tree));
411                 correct = False;
412         }
413
414         return correct;
415 }
416
417 static BOOL rw_torture2(struct cli_state *c1, struct cli_state *c2)
418 {
419         const char *lockfname = "\\torture2.lck";
420         int fnum1;
421         int fnum2;
422         int i;
423         uchar buf[131072];
424         uchar buf_rd[131072];
425         BOOL correct = True;
426         ssize_t bytes_read, bytes_written;
427
428         if (cli_deltree(c1->tree, lockfname) == -1) {
429                 printf("unlink failed (%s)\n", cli_errstr(c1->tree));
430         }
431
432         fnum1 = cli_open(c1->tree, lockfname, O_RDWR | O_CREAT | O_EXCL, 
433                          DENY_NONE);
434         if (fnum1 == -1) {
435                 printf("first open read/write of %s failed (%s)\n",
436                                 lockfname, cli_errstr(c1->tree));
437                 return False;
438         }
439         fnum2 = cli_open(c2->tree, lockfname, O_RDONLY, 
440                          DENY_NONE);
441         if (fnum2 == -1) {
442                 printf("second open read-only of %s failed (%s)\n",
443                                 lockfname, cli_errstr(c2->tree));
444                 cli_close(c1->tree, fnum1);
445                 return False;
446         }
447
448         printf("Checking data integrity over %d ops\n", torture_numops);
449
450         for (i=0;i<torture_numops;i++)
451         {
452                 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
453                 if (i % 10 == 0) {
454                         printf("%d\r", i); fflush(stdout);
455                 }
456
457                 generate_random_buffer(buf, buf_size, False);
458
459                 if ((bytes_written = cli_write(c1->tree, fnum1, 0, buf, 0, buf_size)) != buf_size) {
460                         printf("write failed (%s)\n", cli_errstr(c1->tree));
461                         printf("wrote %d, expected %d\n", bytes_written, buf_size); 
462                         correct = False;
463                         break;
464                 }
465
466                 if ((bytes_read = cli_read(c2->tree, fnum2, buf_rd, 0, buf_size)) != buf_size) {
467                         printf("read failed (%s)\n", cli_errstr(c2->tree));
468                         printf("read %d, expected %d\n", bytes_read, buf_size); 
469                         correct = False;
470                         break;
471                 }
472
473                 if (memcmp(buf_rd, buf, buf_size) != 0)
474                 {
475                         printf("read/write compare failed\n");
476                         correct = False;
477                         break;
478                 }
479         }
480
481         if (NT_STATUS_IS_ERR(cli_close(c2->tree, fnum2))) {
482                 printf("close failed (%s)\n", cli_errstr(c2->tree));
483                 correct = False;
484         }
485         if (NT_STATUS_IS_ERR(cli_close(c1->tree, fnum1))) {
486                 printf("close failed (%s)\n", cli_errstr(c1->tree));
487                 correct = False;
488         }
489
490         if (NT_STATUS_IS_ERR(cli_unlink(c1->tree, lockfname))) {
491                 printf("unlink failed (%s)\n", cli_errstr(c1->tree));
492                 correct = False;
493         }
494
495         return correct;
496 }
497
498 static BOOL run_readwritetest(int dummy)
499 {
500         struct cli_state *cli1, *cli2;
501         BOOL test1, test2 = True;
502
503         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
504                 return False;
505         }
506
507         printf("starting readwritetest\n");
508
509         test1 = rw_torture2(cli1, cli2);
510         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
511
512         if (test1) {
513                 test2 = rw_torture2(cli1, cli1);
514                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
515         }
516
517         if (!torture_close_connection(cli1)) {
518                 test1 = False;
519         }
520
521         if (!torture_close_connection(cli2)) {
522                 test2 = False;
523         }
524
525         return (test1 && test2);
526 }
527
528 static BOOL run_readwritemulti(int dummy)
529 {
530         struct cli_state *cli;
531         BOOL test;
532
533         cli = current_cli;
534
535         test = rw_torture3(cli, "\\multitest.txt");
536
537         if (!torture_close_connection(cli)) {
538                 test = False;
539         }
540         
541         return test;
542 }
543
544
545 int line_count = 0;
546 int nbio_id;
547
548 #define ival(s) strtol(s, NULL, 0)
549
550 /* run a test that simulates an approximate netbench client load */
551 static BOOL run_netbench(int client)
552 {
553         struct cli_state *cli;
554         int i;
555         pstring line;
556         char *cname;
557         FILE *f;
558         const char *params[20];
559         BOOL correct = True;
560
561         cli = current_cli;
562
563         nbio_id = client;
564
565         nb_setup(cli);
566
567         asprintf(&cname, "client%d", client);
568
569         f = fopen(client_txt, "r");
570
571         if (!f) {
572                 perror(client_txt);
573                 return False;
574         }
575
576         while (fgets(line, sizeof(line)-1, f)) {
577                 line_count++;
578
579                 line[strlen(line)-1] = 0;
580
581                 /* printf("[%d] %s\n", line_count, line); */
582
583                 all_string_sub(line,"client1", cname, sizeof(line));
584                 
585                 /* parse the command parameters */
586                 params[0] = strtok(line," ");
587                 i = 0;
588                 while (params[i]) params[++i] = strtok(NULL," ");
589
590                 params[i] = "";
591
592                 if (i < 2) continue;
593
594                 if (!strncmp(params[0],"SMB", 3)) {
595                         printf("ERROR: You are using a dbench 1 load file\n");
596                         exit(1);
597                 }
598                 DEBUG(9,("run_netbench(%d): %s %s\n", client, params[0], params[1]));
599
600                 if (!strcmp(params[0],"NTCreateX")) {
601                         nb_createx(params[1], ival(params[2]), ival(params[3]), 
602                                    ival(params[4]));
603                 } else if (!strcmp(params[0],"Close")) {
604                         nb_close(ival(params[1]));
605                 } else if (!strcmp(params[0],"Rename")) {
606                         nb_rename(params[1], params[2]);
607                 } else if (!strcmp(params[0],"Unlink")) {
608                         nb_unlink(params[1]);
609                 } else if (!strcmp(params[0],"Deltree")) {
610                         nb_deltree(params[1]);
611                 } else if (!strcmp(params[0],"Rmdir")) {
612                         nb_rmdir(params[1]);
613                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
614                         nb_qpathinfo(params[1]);
615                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
616                         nb_qfileinfo(ival(params[1]));
617                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
618                         nb_qfsinfo(ival(params[1]));
619                 } else if (!strcmp(params[0],"FIND_FIRST")) {
620                         nb_findfirst(params[1]);
621                 } else if (!strcmp(params[0],"WriteX")) {
622                         nb_writex(ival(params[1]), 
623                                 ival(params[2]), ival(params[3]), ival(params[4]));
624                 } else if (!strcmp(params[0],"ReadX")) {
625                         nb_readx(ival(params[1]), 
626                       ival(params[2]), ival(params[3]), ival(params[4]));
627                 } else if (!strcmp(params[0],"Flush")) {
628                         nb_flush(ival(params[1]));
629                 } else {
630                         printf("Unknown operation %s\n", params[0]);
631                         exit(1);
632                 }
633         }
634         fclose(f);
635
636         nb_cleanup();
637
638         if (!torture_close_connection(cli)) {
639                 correct = False;
640         }
641         
642         return correct;
643 }
644
645
646 /* run a test that simulates an approximate netbench client load */
647 static BOOL run_nbench(int dummy)
648 {
649         double t;
650         BOOL correct = True;
651
652         nbio_shmem(nprocs);
653
654         nbio_id = -1;
655
656         signal(SIGALRM, SIGNAL_CAST nb_alarm);
657         alarm(1);
658         t = create_procs(run_netbench, &correct);
659         alarm(0);
660
661         printf("\nThroughput %g MB/sec\n", 
662                1.0e-6 * nbio_total() / t);
663         return correct;
664 }
665
666
667 /*
668   This test checks for two things:
669
670   1) correct support for retaining locks over a close (ie. the server
671      must not use posix semantics)
672   2) support for lock timeouts
673  */
674 static BOOL run_locktest1(int dummy)
675 {
676         struct cli_state *cli1, *cli2;
677         const char *fname = "\\lockt1.lck";
678         int fnum1, fnum2, fnum3;
679         time_t t1, t2;
680         unsigned lock_timeout;
681
682         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
683                 return False;
684         }
685
686         printf("starting locktest1\n");
687
688         cli_unlink(cli1->tree, fname);
689
690         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
691         if (fnum1 == -1) {
692                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
693                 return False;
694         }
695         fnum2 = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
696         if (fnum2 == -1) {
697                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
698                 return False;
699         }
700         fnum3 = cli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
701         if (fnum3 == -1) {
702                 printf("open3 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
703                 return False;
704         }
705
706         if (NT_STATUS_IS_ERR(cli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
707                 printf("lock1 failed (%s)\n", cli_errstr(cli1->tree));
708                 return False;
709         }
710
711
712         if (NT_STATUS_IS_OK(cli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
713                 printf("lock2 succeeded! This is a locking bug\n");
714                 return False;
715         } else {
716                 if (!check_error(__LINE__, cli2, ERRDOS, ERRlock, 
717                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
718         }
719
720
721         lock_timeout = (6 + (random() % 20));
722         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
723         t1 = time(NULL);
724         if (NT_STATUS_IS_OK(cli_lock(cli2->tree, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK))) {
725                 printf("lock3 succeeded! This is a locking bug\n");
726                 return False;
727         } else {
728                 if (!check_error(__LINE__, cli2, ERRDOS, ERRlock, 
729                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
730         }
731         t2 = time(NULL);
732
733         if (t2 - t1 < 5) {
734                 printf("error: This server appears not to support timed lock requests\n");
735         }
736         printf("server slept for %u seconds for a %u second timeout\n",
737                (unsigned int)(t2-t1), lock_timeout);
738
739         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum2))) {
740                 printf("close1 failed (%s)\n", cli_errstr(cli1->tree));
741                 return False;
742         }
743
744         if (NT_STATUS_IS_OK(cli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
745                 printf("lock4 succeeded! This is a locking bug\n");
746                 return False;
747         } else {
748                 if (!check_error(__LINE__, cli2, ERRDOS, ERRlock, 
749                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
750         }
751
752         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
753                 printf("close2 failed (%s)\n", cli_errstr(cli1->tree));
754                 return False;
755         }
756
757         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum3))) {
758                 printf("close3 failed (%s)\n", cli_errstr(cli2->tree));
759                 return False;
760         }
761
762         if (NT_STATUS_IS_ERR(cli_unlink(cli1->tree, fname))) {
763                 printf("unlink failed (%s)\n", cli_errstr(cli1->tree));
764                 return False;
765         }
766
767
768         if (!torture_close_connection(cli1)) {
769                 return False;
770         }
771
772         if (!torture_close_connection(cli2)) {
773                 return False;
774         }
775
776         printf("Passed locktest1\n");
777         return True;
778 }
779
780 /*
781   this checks to see if a secondary tconx can use open files from an
782   earlier tconx
783  */
784 static BOOL run_tcon_test(int dummy)
785 {
786         struct cli_state *cli;
787         const char *fname = "\\tcontest.tmp";
788         int fnum1;
789         uint16 cnum1, cnum2, cnum3;
790         uint16 vuid1, vuid2;
791         char buf[4];
792         BOOL ret = True;
793         struct cli_tree *tree1;
794         char *host = lp_parm_string(-1, "torture", "host");
795         char *share = lp_parm_string(-1, "torture", "share");
796         char *password = lp_parm_string(-1, "torture", "password");
797
798         if (!torture_open_connection(&cli)) {
799                 return False;
800         }
801
802         printf("starting tcontest\n");
803
804         if (cli_deltree(cli->tree, fname) == -1) {
805                 printf("unlink of %s failed (%s)\n", fname, cli_errstr(cli->tree));
806         }
807
808         fnum1 = cli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
809         if (fnum1 == -1) {
810                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli->tree));
811                 return False;
812         }
813
814         cnum1 = cli->tree->tid;
815         vuid1 = cli->session->vuid;
816
817         memset(&buf, 0, 4); /* init buf so valgrind won't complain */
818         if (cli_write(cli->tree, fnum1, 0, buf, 130, 4) != 4) {
819                 printf("initial write failed (%s)\n", cli_errstr(cli->tree));
820                 return False;
821         }
822
823         tree1 = cli->tree;      /* save old tree connection */
824         if (NT_STATUS_IS_ERR(cli_send_tconX(cli, share, "?????", password))) {
825                 printf("%s refused 2nd tree connect (%s)\n", host,
826                            cli_errstr(cli->tree));
827                 cli_shutdown(cli);
828                 return False;
829         }
830
831         cnum2 = cli->tree->tid;
832         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
833         vuid2 = cli->session->vuid + 1;
834
835         /* try a write with the wrong tid */
836         cli->tree->tid = cnum2;
837
838         if (cli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
839                 printf("* server allows write with wrong TID\n");
840                 ret = False;
841         } else {
842                 printf("server fails write with wrong TID : %s\n", cli_errstr(cli->tree));
843         }
844
845
846         /* try a write with an invalid tid */
847         cli->tree->tid = cnum3;
848
849         if (cli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
850                 printf("* server allows write with invalid TID\n");
851                 ret = False;
852         } else {
853                 printf("server fails write with invalid TID : %s\n", cli_errstr(cli->tree));
854         }
855
856         /* try a write with an invalid vuid */
857         cli->session->vuid = vuid2;
858         cli->tree->tid = cnum1;
859
860         if (cli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
861                 printf("* server allows write with invalid VUID\n");
862                 ret = False;
863         } else {
864                 printf("server fails write with invalid VUID : %s\n", cli_errstr(cli->tree));
865         }
866
867         cli->session->vuid = vuid1;
868         cli->tree->tid = cnum1;
869
870         if (NT_STATUS_IS_ERR(cli_close(cli->tree, fnum1))) {
871                 printf("close failed (%s)\n", cli_errstr(cli->tree));
872                 return False;
873         }
874
875         cli->tree->tid = cnum2;
876
877         if (NT_STATUS_IS_ERR(cli_tdis(cli))) {
878                 printf("secondary tdis failed (%s)\n", cli_errstr(cli->tree));
879                 return False;
880         }
881
882         cli->tree = tree1;  /* restore initial tree */
883         cli->tree->tid = cnum1;
884
885         if (!torture_close_connection(cli)) {
886                 return False;
887         }
888
889         return ret;
890 }
891
892
893
894 static BOOL tcon_devtest(struct cli_state *cli,
895                          const char *myshare, const char *devtype,
896                          NTSTATUS expected_error)
897 {
898         BOOL status;
899         BOOL ret;
900         char *password = lp_parm_string(-1, "torture", "password");
901
902         status = NT_STATUS_IS_OK(cli_send_tconX(cli, myshare, devtype, 
903                                                 password));
904
905         printf("Trying share %s with devtype %s\n", myshare, devtype);
906
907         if (NT_STATUS_IS_OK(expected_error)) {
908                 if (status) {
909                         ret = True;
910                 } else {
911                         printf("tconX to share %s with type %s "
912                                "should have succeeded but failed\n",
913                                myshare, devtype);
914                         ret = False;
915                 }
916                 cli_tdis(cli);
917         } else {
918                 if (status) {
919                         printf("tconx to share %s with type %s "
920                                "should have failed but succeeded\n",
921                                myshare, devtype);
922                         ret = False;
923                 } else {
924                         if (NT_STATUS_EQUAL(cli_nt_error(cli->tree),
925                                             expected_error)) {
926                                 ret = True;
927                         } else {
928                                 printf("Returned unexpected error\n");
929                                 ret = False;
930                         }
931                 }
932         }
933         return ret;
934 }
935
936 /*
937  checks for correct tconX support
938  */
939 static BOOL run_tcon_devtype_test(int dummy)
940 {
941         struct cli_state *cli1 = NULL;
942         BOOL retry;
943         int flags = 0;
944         NTSTATUS status;
945         BOOL ret = True;
946         char *host = lp_parm_string(-1, "torture", "host");
947         char *share = lp_parm_string(-1, "torture", "share");
948         char *username = lp_parm_string(-1, "torture", "username");
949         char *password = lp_parm_string(-1, "torture", "password");
950         
951         status = cli_full_connection(&cli1, lp_netbios_name(),
952                                      host, NULL, 
953                                      share, "?????",
954                                      username, lp_workgroup(),
955                                      password, flags, &retry);
956
957         if (!NT_STATUS_IS_OK(status)) {
958                 printf("could not open connection\n");
959                 return False;
960         }
961
962         if (!tcon_devtest(cli1, "IPC$", "A:", NT_STATUS_BAD_DEVICE_TYPE))
963                 ret = False;
964
965         if (!tcon_devtest(cli1, "IPC$", "?????", NT_STATUS_OK))
966                 ret = False;
967
968         if (!tcon_devtest(cli1, "IPC$", "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
969                 ret = False;
970
971         if (!tcon_devtest(cli1, "IPC$", "IPC", NT_STATUS_OK))
972                 ret = False;
973                         
974         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
975                 ret = False;
976
977         if (!tcon_devtest(cli1, share, "A:", NT_STATUS_OK))
978                 ret = False;
979
980         if (!tcon_devtest(cli1, share, "?????", NT_STATUS_OK))
981                 ret = False;
982
983         if (!tcon_devtest(cli1, share, "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
984                 ret = False;
985
986         if (!tcon_devtest(cli1, share, "IPC", NT_STATUS_BAD_DEVICE_TYPE))
987                 ret = False;
988                         
989         if (!tcon_devtest(cli1, share, "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
990                 ret = False;
991
992         cli_shutdown(cli1);
993
994         if (ret)
995                 printf("Passed tcondevtest\n");
996
997         return ret;
998 }
999
1000
1001 /*
1002   This test checks that 
1003
1004   1) the server supports multiple locking contexts on the one SMB
1005   connection, distinguished by PID.  
1006
1007   2) the server correctly fails overlapping locks made by the same PID (this
1008      goes against POSIX behaviour, which is why it is tricky to implement)
1009
1010   3) the server denies unlock requests by an incorrect client PID
1011 */
1012 static BOOL run_locktest2(int dummy)
1013 {
1014         struct cli_state *cli;
1015         const char *fname = "\\lockt2.lck";
1016         int fnum1, fnum2, fnum3;
1017         BOOL correct = True;
1018
1019         if (!torture_open_connection(&cli)) {
1020                 return False;
1021         }
1022
1023         printf("starting locktest2\n");
1024
1025         cli_unlink(cli->tree, fname);
1026
1027         printf("Testing pid context\n");
1028         
1029         cli->session->pid = 1;
1030
1031         fnum1 = cli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1032         if (fnum1 == -1) {
1033                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli->tree));
1034                 return False;
1035         }
1036
1037         fnum2 = cli_open(cli->tree, fname, O_RDWR, DENY_NONE);
1038         if (fnum2 == -1) {
1039                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(cli->tree));
1040                 return False;
1041         }
1042
1043         cli->session->pid = 2;
1044
1045         fnum3 = cli_open(cli->tree, fname, O_RDWR, DENY_NONE);
1046         if (fnum3 == -1) {
1047                 printf("open3 of %s failed (%s)\n", fname, cli_errstr(cli->tree));
1048                 return False;
1049         }
1050
1051         cli->session->pid = 1;
1052
1053         if (NT_STATUS_IS_ERR(cli_lock(cli->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
1054                 printf("lock1 failed (%s)\n", cli_errstr(cli->tree));
1055                 return False;
1056         }
1057
1058         if (NT_STATUS_IS_OK(cli_lock(cli->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
1059                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1060                 correct = False;
1061         } else {
1062                 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, 
1063                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
1064         }
1065
1066         if (NT_STATUS_IS_OK(cli_lock(cli->tree, fnum2, 0, 4, 0, WRITE_LOCK))) {
1067                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1068                 correct = False;
1069         } else {
1070                 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, 
1071                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
1072         }
1073
1074         if (NT_STATUS_IS_OK(cli_lock(cli->tree, fnum2, 0, 4, 0, READ_LOCK))) {
1075                 printf("READ lock2 succeeded! This is a locking bug\n");
1076                 correct = False;
1077         } else {
1078                 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, 
1079                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
1080         }
1081
1082         if (NT_STATUS_IS_ERR(cli_lock(cli->tree, fnum1, 100, 4, 0, WRITE_LOCK))) {
1083                 printf("lock at 100 failed (%s)\n", cli_errstr(cli->tree));
1084         }
1085
1086         cli->session->pid = 2;
1087
1088         if (NT_STATUS_IS_OK(cli_unlock(cli->tree, fnum1, 100, 4))) {
1089                 printf("unlock at 100 succeeded! This is a locking bug\n");
1090                 correct = False;
1091         }
1092
1093         if (NT_STATUS_IS_OK(cli_unlock(cli->tree, fnum1, 0, 4))) {
1094                 printf("unlock1 succeeded! This is a locking bug\n");
1095                 correct = False;
1096         } else {
1097                 if (!check_error(__LINE__, cli, 
1098                                  ERRDOS, ERRlock, 
1099                                  NT_STATUS_RANGE_NOT_LOCKED)) return False;
1100         }
1101
1102         if (NT_STATUS_IS_OK(cli_unlock(cli->tree, fnum1, 0, 8))) {
1103                 printf("unlock2 succeeded! This is a locking bug\n");
1104                 correct = False;
1105         } else {
1106                 if (!check_error(__LINE__, cli, 
1107                                  ERRDOS, ERRlock, 
1108                                  NT_STATUS_RANGE_NOT_LOCKED)) return False;
1109         }
1110
1111         if (NT_STATUS_IS_OK(cli_lock(cli->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
1112                 printf("lock3 succeeded! This is a locking bug\n");
1113                 correct = False;
1114         } else {
1115                 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
1116         }
1117
1118         cli->session->pid = 1;
1119
1120         if (NT_STATUS_IS_ERR(cli_close(cli->tree, fnum1))) {
1121                 printf("close1 failed (%s)\n", cli_errstr(cli->tree));
1122                 return False;
1123         }
1124
1125         if (NT_STATUS_IS_ERR(cli_close(cli->tree, fnum2))) {
1126                 printf("close2 failed (%s)\n", cli_errstr(cli->tree));
1127                 return False;
1128         }
1129
1130         if (NT_STATUS_IS_ERR(cli_close(cli->tree, fnum3))) {
1131                 printf("close3 failed (%s)\n", cli_errstr(cli->tree));
1132                 return False;
1133         }
1134
1135         if (!torture_close_connection(cli)) {
1136                 correct = False;
1137         }
1138
1139         printf("locktest2 finished\n");
1140
1141         return correct;
1142 }
1143
1144
1145 /*
1146   This test checks that 
1147
1148   1) the server supports the full offset range in lock requests
1149 */
1150 static BOOL run_locktest3(int dummy)
1151 {
1152         struct cli_state *cli1, *cli2;
1153         const char *fname = "\\lockt3.lck";
1154         int fnum1, fnum2, i;
1155         uint32 offset;
1156         BOOL correct = True;
1157
1158 #define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
1159
1160         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
1161                 return False;
1162         }
1163
1164         printf("starting locktest3\n");
1165
1166         printf("Testing 32 bit offset ranges\n");
1167
1168         cli_unlink(cli1->tree, fname);
1169
1170         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1171         if (fnum1 == -1) {
1172                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
1173                 return False;
1174         }
1175         fnum2 = cli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
1176         if (fnum2 == -1) {
1177                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
1178                 return False;
1179         }
1180
1181         printf("Establishing %d locks\n", torture_numops);
1182
1183         for (offset=i=0;i<torture_numops;i++) {
1184                 NEXT_OFFSET;
1185                 if (NT_STATUS_IS_ERR(cli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK))) {
1186                         printf("lock1 %d failed (%s)\n", 
1187                                i,
1188                                cli_errstr(cli1->tree));
1189                         return False;
1190                 }
1191
1192                 if (NT_STATUS_IS_ERR(cli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK))) {
1193                         printf("lock2 %d failed (%s)\n", 
1194                                i,
1195                                cli_errstr(cli1->tree));
1196                         return False;
1197                 }
1198         }
1199
1200         printf("Testing %d locks\n", torture_numops);
1201
1202         for (offset=i=0;i<torture_numops;i++) {
1203                 NEXT_OFFSET;
1204
1205                 if (NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, offset-2, 1, 0, WRITE_LOCK))) {
1206                         printf("error: lock1 %d succeeded!\n", i);
1207                         return False;
1208                 }
1209
1210                 if (NT_STATUS_IS_OK(cli_lock(cli2->tree, fnum2, offset-1, 1, 0, WRITE_LOCK))) {
1211                         printf("error: lock2 %d succeeded!\n", i);
1212                         return False;
1213                 }
1214
1215                 if (NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK))) {
1216                         printf("error: lock3 %d succeeded!\n", i);
1217                         return False;
1218                 }
1219
1220                 if (NT_STATUS_IS_OK(cli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK))) {
1221                         printf("error: lock4 %d succeeded!\n", i);
1222                         return False;
1223                 }
1224         }
1225
1226         printf("Removing %d locks\n", torture_numops);
1227
1228         for (offset=i=0;i<torture_numops;i++) {
1229                 NEXT_OFFSET;
1230
1231                 if (NT_STATUS_IS_ERR(cli_unlock(cli1->tree, fnum1, offset-1, 1))) {
1232                         printf("unlock1 %d failed (%s)\n", 
1233                                i,
1234                                cli_errstr(cli1->tree));
1235                         return False;
1236                 }
1237
1238                 if (NT_STATUS_IS_ERR(cli_unlock(cli2->tree, fnum2, offset-2, 1))) {
1239                         printf("unlock2 %d failed (%s)\n", 
1240                                i,
1241                                cli_errstr(cli1->tree));
1242                         return False;
1243                 }
1244         }
1245
1246         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
1247                 printf("close1 failed (%s)\n", cli_errstr(cli1->tree));
1248                 return False;
1249         }
1250
1251         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum2))) {
1252                 printf("close2 failed (%s)\n", cli_errstr(cli2->tree));
1253                 return False;
1254         }
1255
1256         if (NT_STATUS_IS_ERR(cli_unlink(cli1->tree, fname))) {
1257                 printf("unlink failed (%s)\n", cli_errstr(cli1->tree));
1258                 return False;
1259         }
1260
1261         if (!torture_close_connection(cli1)) {
1262                 correct = False;
1263         }
1264         
1265         if (!torture_close_connection(cli2)) {
1266                 correct = False;
1267         }
1268
1269         printf("finished locktest3\n");
1270
1271         return correct;
1272 }
1273
1274 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1275         printf("** "); correct = False; \
1276         }
1277
1278 /*
1279   looks at overlapping locks
1280 */
1281 static BOOL run_locktest4(int dummy)
1282 {
1283         struct cli_state *cli1, *cli2;
1284         const char *fname = "\\lockt4.lck";
1285         int fnum1, fnum2, f;
1286         BOOL ret;
1287         char buf[1000];
1288         BOOL correct = True;
1289
1290         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
1291                 return False;
1292         }
1293
1294         printf("starting locktest4\n");
1295
1296         cli_unlink(cli1->tree, fname);
1297
1298         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1299         fnum2 = cli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
1300
1301         memset(buf, 0, sizeof(buf));
1302
1303         if (cli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1304                 printf("Failed to create file\n");
1305                 correct = False;
1306                 goto fail;
1307         }
1308
1309         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1310               NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 2, 4, 0, WRITE_LOCK));
1311         EXPECTED(ret, False);
1312         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1313             
1314         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 10, 4, 0, READ_LOCK)) &&
1315               NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 12, 4, 0, READ_LOCK));
1316         EXPECTED(ret, True);
1317         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1318
1319         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1320               NT_STATUS_IS_OK(cli_lock(cli2->tree, fnum2, 22, 4, 0, WRITE_LOCK));
1321         EXPECTED(ret, False);
1322         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1323             
1324         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 30, 4, 0, READ_LOCK)) &&
1325                 NT_STATUS_IS_OK(cli_lock(cli2->tree, fnum2, 32, 4, 0, READ_LOCK));
1326         EXPECTED(ret, True);
1327         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1328         
1329         ret = NT_STATUS_IS_OK((cli1->session->pid = 1, cli_lock(cli1->tree, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1330               NT_STATUS_IS_OK((cli1->session->pid = 2, cli_lock(cli1->tree, fnum1, 42, 4, 0, WRITE_LOCK)));
1331         EXPECTED(ret, False);
1332         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1333             
1334         ret = NT_STATUS_IS_OK((cli1->session->pid = 1, cli_lock(cli1->tree, fnum1, 50, 4, 0, READ_LOCK))) &&
1335               NT_STATUS_IS_OK((cli1->session->pid = 2, cli_lock(cli1->tree, fnum1, 52, 4, 0, READ_LOCK)));
1336         EXPECTED(ret, True);
1337         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1338
1339         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK)) &&
1340               NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK));
1341         EXPECTED(ret, True);
1342         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1343
1344         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1345               NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK));
1346         EXPECTED(ret, False);
1347         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1348
1349         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 80, 4, 0, READ_LOCK)) &&
1350               NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 80, 4, 0, WRITE_LOCK));
1351         EXPECTED(ret, False);
1352         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1353
1354         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 90, 4, 0, WRITE_LOCK)) &&
1355               NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 90, 4, 0, READ_LOCK));
1356         EXPECTED(ret, True);
1357         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1358
1359         ret = NT_STATUS_IS_OK((cli1->session->pid = 1, cli_lock(cli1->tree, fnum1, 100, 4, 0, WRITE_LOCK))) &&
1360               NT_STATUS_IS_OK((cli1->session->pid = 2, cli_lock(cli1->tree, fnum1, 100, 4, 0, READ_LOCK)));
1361         EXPECTED(ret, False);
1362         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1363
1364         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 110, 4, 0, READ_LOCK)) &&
1365               NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 112, 4, 0, READ_LOCK)) &&
1366               NT_STATUS_IS_OK(cli_unlock(cli1->tree, fnum1, 110, 6));
1367         EXPECTED(ret, False);
1368         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
1369
1370
1371         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 120, 4, 0, WRITE_LOCK)) &&
1372               (cli_read(cli2->tree, fnum2, buf, 120, 4) == 4);
1373         EXPECTED(ret, False);
1374         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
1375
1376         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK)) &&
1377               (cli_write(cli2->tree, fnum2, 0, buf, 130, 4) == 4);
1378         EXPECTED(ret, False);
1379         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
1380
1381
1382         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) &&
1383               NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) &&
1384               NT_STATUS_IS_OK(cli_unlock(cli1->tree, fnum1, 140, 4)) &&
1385               NT_STATUS_IS_OK(cli_unlock(cli1->tree, fnum1, 140, 4));
1386         EXPECTED(ret, True);
1387         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
1388
1389
1390         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 150, 4, 0, WRITE_LOCK)) &&
1391               NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 150, 4, 0, READ_LOCK)) &&
1392               NT_STATUS_IS_OK(cli_unlock(cli1->tree, fnum1, 150, 4)) &&
1393               (cli_read(cli2->tree, fnum2, buf, 150, 4) == 4) &&
1394               !(cli_write(cli2->tree, fnum2, 0, buf, 150, 4) == 4) &&
1395               NT_STATUS_IS_OK(cli_unlock(cli1->tree, fnum1, 150, 4));
1396         EXPECTED(ret, True);
1397         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
1398
1399         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 160, 4, 0, READ_LOCK)) &&
1400               NT_STATUS_IS_OK(cli_unlock(cli1->tree, fnum1, 160, 4)) &&
1401               (cli_write(cli2->tree, fnum2, 0, buf, 160, 4) == 4) &&            
1402               (cli_read(cli2->tree, fnum2, buf, 160, 4) == 4);          
1403         EXPECTED(ret, True);
1404         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
1405
1406         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 170, 4, 0, WRITE_LOCK)) &&
1407               NT_STATUS_IS_OK(cli_unlock(cli1->tree, fnum1, 170, 4)) &&
1408               (cli_write(cli2->tree, fnum2, 0, buf, 170, 4) == 4) &&            
1409               (cli_read(cli2->tree, fnum2, buf, 170, 4) == 4);          
1410         EXPECTED(ret, True);
1411         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
1412
1413         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 190, 4, 0, WRITE_LOCK)) &&
1414               NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 190, 4, 0, READ_LOCK)) &&
1415               NT_STATUS_IS_OK(cli_unlock(cli1->tree, fnum1, 190, 4)) &&
1416               !(cli_write(cli2->tree, fnum2, 0, buf, 190, 4) == 4) &&           
1417               (cli_read(cli2->tree, fnum2, buf, 190, 4) == 4);          
1418         EXPECTED(ret, True);
1419         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
1420
1421         cli_close(cli1->tree, fnum1);
1422         cli_close(cli2->tree, fnum2);
1423         fnum1 = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1424         f = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1425         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) &&
1426               NT_STATUS_IS_OK(cli_lock(cli1->tree, f, 0, 1, 0, READ_LOCK)) &&
1427               NT_STATUS_IS_OK(cli_close(cli1->tree, fnum1)) &&
1428               ((fnum1 = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE)) != -1) &&
1429               NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK));
1430         cli_close(cli1->tree, f);
1431         cli_close(cli1->tree, fnum1);
1432         EXPECTED(ret, True);
1433         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
1434
1435  fail:
1436         cli_close(cli1->tree, fnum1);
1437         cli_close(cli2->tree, fnum2);
1438         cli_unlink(cli1->tree, fname);
1439         torture_close_connection(cli1);
1440         torture_close_connection(cli2);
1441
1442         printf("finished locktest4\n");
1443         return correct;
1444 }
1445
1446 /*
1447   looks at lock upgrade/downgrade.
1448 */
1449 static BOOL run_locktest5(int dummy)
1450 {
1451         struct cli_state *cli1, *cli2;
1452         const char *fname = "\\lockt5.lck";
1453         int fnum1, fnum2, fnum3;
1454         BOOL ret;
1455         char buf[1000];
1456         BOOL correct = True;
1457
1458         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
1459                 return False;
1460         }
1461
1462         printf("starting locktest5\n");
1463
1464         cli_unlink(cli1->tree, fname);
1465
1466         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1467         fnum2 = cli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
1468         fnum3 = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1469
1470         memset(buf, 0, sizeof(buf));
1471
1472         if (cli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1473                 printf("Failed to create file\n");
1474                 correct = False;
1475                 goto fail;
1476         }
1477
1478         /* Check for NT bug... */
1479         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) &&
1480                   NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum3, 0, 1, 0, READ_LOCK));
1481         cli_close(cli1->tree, fnum1);
1482         fnum1 = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1483         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK));
1484         EXPECTED(ret, True);
1485         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
1486         cli_close(cli1->tree, fnum1);
1487         fnum1 = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1488         cli_unlock(cli1->tree, fnum3, 0, 1);
1489
1490         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1491               NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 1, 1, 0, READ_LOCK));
1492         EXPECTED(ret, True);
1493         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
1494
1495         ret = NT_STATUS_IS_OK(cli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK));
1496         EXPECTED(ret, False);
1497
1498         printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
1499
1500         /* Unlock the process 2 lock. */
1501         cli_unlock(cli2->tree, fnum2, 0, 4);
1502
1503         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum3, 0, 4, 0, READ_LOCK));
1504         EXPECTED(ret, False);
1505
1506         printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
1507
1508         /* Unlock the process 1 fnum3 lock. */
1509         cli_unlock(cli1->tree, fnum3, 0, 4);
1510
1511         /* Stack 2 more locks here. */
1512         ret = NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK)) &&
1513                   NT_STATUS_IS_OK(cli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK));
1514
1515         EXPECTED(ret, True);
1516         printf("the same process %s stack read locks\n", ret?"can":"cannot");
1517
1518         /* Unlock the first process lock, then check this was the WRITE lock that was
1519                 removed. */
1520
1521 ret = NT_STATUS_IS_OK(cli_unlock(cli1->tree, fnum1, 0, 4)) &&
1522         NT_STATUS_IS_OK(cli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK));
1523
1524         EXPECTED(ret, True);
1525         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
1526
1527         /* Unlock the process 2 lock. */
1528         cli_unlock(cli2->tree, fnum2, 0, 4);
1529
1530         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
1531
1532         ret = NT_STATUS_IS_OK(cli_unlock(cli1->tree, fnum1, 1, 1)) &&
1533                   NT_STATUS_IS_OK(cli_unlock(cli1->tree, fnum1, 0, 4)) &&
1534                   NT_STATUS_IS_OK(cli_unlock(cli1->tree, fnum1, 0, 4));
1535
1536         EXPECTED(ret, True);
1537         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
1538
1539         /* Ensure the next unlock fails. */
1540         ret = NT_STATUS_IS_OK(cli_unlock(cli1->tree, fnum1, 0, 4));
1541         EXPECTED(ret, False);
1542         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
1543
1544         /* Ensure connection 2 can get a write lock. */
1545         ret = NT_STATUS_IS_OK(cli_lock(cli2->tree, fnum2, 0, 4, 0, WRITE_LOCK));
1546         EXPECTED(ret, True);
1547
1548         printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
1549
1550
1551  fail:
1552         cli_close(cli1->tree, fnum1);
1553         cli_close(cli2->tree, fnum2);
1554         cli_unlink(cli1->tree, fname);
1555         if (!torture_close_connection(cli1)) {
1556                 correct = False;
1557         }
1558         if (!torture_close_connection(cli2)) {
1559                 correct = False;
1560         }
1561
1562         printf("finished locktest5\n");
1563        
1564         return correct;
1565 }
1566
1567 /*
1568   tries the unusual lockingX locktype bits
1569 */
1570 static BOOL run_locktest6(int dummy)
1571 {
1572         struct cli_state *cli;
1573         const char *fname[1] = { "\\lock6.txt" };
1574         int i;
1575         int fnum;
1576         NTSTATUS status;
1577
1578         if (!torture_open_connection(&cli)) {
1579                 return False;
1580         }
1581
1582         printf("starting locktest6\n");
1583
1584         for (i=0;i<1;i++) {
1585                 printf("Testing %s\n", fname[i]);
1586
1587                 cli_unlink(cli->tree, fname[i]);
1588
1589                 fnum = cli_open(cli->tree, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1590                 status = cli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
1591                 cli_close(cli->tree, fnum);
1592                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
1593
1594                 fnum = cli_open(cli->tree, fname[i], O_RDWR, DENY_NONE);
1595                 status = cli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
1596                 cli_close(cli->tree, fnum);
1597                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
1598
1599                 cli_unlink(cli->tree, fname[i]);
1600         }
1601
1602         torture_close_connection(cli);
1603
1604         printf("finished locktest6\n");
1605         return True;
1606 }
1607
1608 static BOOL run_locktest7(int dummy)
1609 {
1610         struct cli_state *cli1;
1611         const char *fname = "\\lockt7.lck";
1612         int fnum1;
1613         char buf[200];
1614         BOOL correct = False;
1615
1616         if (!torture_open_connection(&cli1)) {
1617                 return False;
1618         }
1619
1620         printf("starting locktest7\n");
1621
1622         cli_unlink(cli1->tree, fname);
1623
1624         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1625
1626         memset(buf, 0, sizeof(buf));
1627
1628         if (cli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1629                 printf("Failed to create file\n");
1630                 goto fail;
1631         }
1632
1633         cli1->session->pid = 1;
1634
1635         if (NT_STATUS_IS_ERR(cli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK))) {
1636                 printf("Unable to apply read lock on range 130:4, error was %s\n", cli_errstr(cli1->tree));
1637                 goto fail;
1638         } else {
1639                 printf("pid1 successfully locked range 130:4 for READ\n");
1640         }
1641
1642         if (cli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
1643                 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1644                 goto fail;
1645         } else {
1646                 printf("pid1 successfully read the range 130:4\n");
1647         }
1648
1649         if (cli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
1650                 printf("pid1 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1651                 if (NT_STATUS_V(cli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
1652                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
1653                         goto fail;
1654                 }
1655         } else {
1656                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
1657                 goto fail;
1658         }
1659
1660         cli1->session->pid = 2;
1661
1662         if (cli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
1663                 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1664         } else {
1665                 printf("pid2 successfully read the range 130:4\n");
1666         }
1667
1668         if (cli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
1669                 printf("pid2 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1670                 if (NT_STATUS_V(cli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
1671                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
1672                         goto fail;
1673                 }
1674         } else {
1675                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
1676                 goto fail;
1677         }
1678
1679         cli1->session->pid = 1;
1680         cli_unlock(cli1->tree, fnum1, 130, 4);
1681
1682         if (NT_STATUS_IS_ERR(cli_lock(cli1->tree, fnum1, 130, 4, 0, WRITE_LOCK))) {
1683                 printf("Unable to apply write lock on range 130:4, error was %s\n", cli_errstr(cli1->tree));
1684                 goto fail;
1685         } else {
1686                 printf("pid1 successfully locked range 130:4 for WRITE\n");
1687         }
1688
1689         if (cli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
1690                 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1691                 goto fail;
1692         } else {
1693                 printf("pid1 successfully read the range 130:4\n");
1694         }
1695
1696         if (cli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
1697                 printf("pid1 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1698                 goto fail;
1699         } else {
1700                 printf("pid1 successfully wrote to the range 130:4\n");
1701         }
1702
1703         cli1->session->pid = 2;
1704
1705         if (cli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
1706                 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1707                 if (NT_STATUS_V(cli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
1708                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
1709                         goto fail;
1710                 }
1711         } else {
1712                 printf("pid2 successfully read the range 130:4 (should be denied)\n");
1713                 goto fail;
1714         }
1715
1716         if (cli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
1717                 printf("pid2 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1718                 if (NT_STATUS_V(cli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
1719                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
1720                         goto fail;
1721                 }
1722         } else {
1723                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
1724                 goto fail;
1725         }
1726
1727         cli_unlock(cli1->tree, fnum1, 130, 0);
1728         correct = True;
1729
1730 fail:
1731         cli_close(cli1->tree, fnum1);
1732         cli_unlink(cli1->tree, fname);
1733         torture_close_connection(cli1);
1734
1735         printf("finished locktest7\n");
1736         return correct;
1737 }
1738
1739 /*
1740 test whether fnums and tids open on one VC are available on another (a major
1741 security hole)
1742 */
1743 static BOOL run_fdpasstest(int dummy)
1744 {
1745         struct cli_state *cli1, *cli2;
1746         const char *fname = "\\fdpass.tst";
1747         int fnum1, oldtid;
1748         pstring buf;
1749
1750         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
1751                 return False;
1752         }
1753
1754         printf("starting fdpasstest\n");
1755
1756         cli_unlink(cli1->tree, fname);
1757
1758         printf("Opening a file on connection 1\n");
1759
1760         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1761         if (fnum1 == -1) {
1762                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
1763                 return False;
1764         }
1765
1766         printf("writing to file on connection 1\n");
1767
1768         if (cli_write(cli1->tree, fnum1, 0, "hello world\n", 0, 13) != 13) {
1769                 printf("write failed (%s)\n", cli_errstr(cli1->tree));
1770                 return False;
1771         }
1772
1773         oldtid = cli2->tree->tid;
1774         cli2->session->vuid = cli1->session->vuid;
1775         cli2->tree->tid = cli1->tree->tid;
1776         cli2->session->pid = cli1->session->pid;
1777
1778         printf("reading from file on connection 2\n");
1779
1780         if (cli_read(cli2->tree, fnum1, buf, 0, 13) == 13) {
1781                 printf("read succeeded! nasty security hole [%s]\n",
1782                        buf);
1783                 return False;
1784         }
1785
1786         cli_close(cli1->tree, fnum1);
1787         cli_unlink(cli1->tree, fname);
1788
1789         cli2->tree->tid = oldtid;
1790
1791         torture_close_connection(cli1);
1792         torture_close_connection(cli2);
1793
1794         printf("finished fdpasstest\n");
1795         return True;
1796 }
1797
1798
1799 /*
1800   This test checks that 
1801
1802   1) the server does not allow an unlink on a file that is open
1803 */
1804 static BOOL run_unlinktest(int dummy)
1805 {
1806         struct cli_state *cli;
1807         const char *fname = "\\unlink.tst";
1808         int fnum;
1809         BOOL correct = True;
1810
1811         if (!torture_open_connection(&cli)) {
1812                 return False;
1813         }
1814
1815         printf("starting unlink test\n");
1816
1817         cli_unlink(cli->tree, fname);
1818
1819         cli->session->pid = 1;
1820
1821         printf("Opening a file\n");
1822
1823         fnum = cli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1824         if (fnum == -1) {
1825                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli->tree));
1826                 return False;
1827         }
1828
1829         printf("Unlinking a open file\n");
1830
1831         if (NT_STATUS_IS_OK(cli_unlink(cli->tree, fname))) {
1832                 printf("error: server allowed unlink on an open file\n");
1833                 correct = False;
1834         } else {
1835                 correct = check_error(__LINE__, cli, ERRDOS, ERRbadshare, 
1836                                       NT_STATUS_SHARING_VIOLATION);
1837         }
1838
1839         cli_close(cli->tree, fnum);
1840         cli_unlink(cli->tree, fname);
1841
1842         if (!torture_close_connection(cli)) {
1843                 correct = False;
1844         }
1845
1846         printf("unlink test finished\n");
1847         
1848         return correct;
1849 }
1850
1851
1852 /*
1853 test how many open files this server supports on the one socket
1854 */
1855 static BOOL run_maxfidtest(int dummy)
1856 {
1857         struct cli_state *cli;
1858         const char *template = "\\maxfid.%d.%d";
1859         char *fname;
1860         int fnums[0x11000], i;
1861         int retries=4;
1862         BOOL correct = True;
1863
1864         cli = current_cli;
1865
1866         if (retries <= 0) {
1867                 printf("failed to connect\n");
1868                 return False;
1869         }
1870
1871         printf("Testing maximum number of open files\n");
1872
1873         for (i=0; i<0x11000; i++) {
1874                 asprintf(&fname, template, i,(int)getpid());
1875                 if ((fnums[i] = cli_open(cli->tree, fname, 
1876                                         O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) ==
1877                     -1) {
1878                         printf("open of %s failed (%s)\n", 
1879                                fname, cli_errstr(cli->tree));
1880                         printf("maximum fnum is %d\n", i);
1881                         break;
1882                 }
1883                 free(fname);
1884                 printf("%6d\r", i);
1885         }
1886         printf("%6d\n", i);
1887         i--;
1888
1889         printf("cleaning up\n");
1890         for (;i>=0;i--) {
1891                 asprintf(&fname, template, i,(int)getpid());
1892                 if (NT_STATUS_IS_ERR(cli_close(cli->tree, fnums[i]))) {
1893                         printf("Close of fnum %d failed - %s\n", fnums[i], cli_errstr(cli->tree));
1894                 }
1895                 if (NT_STATUS_IS_ERR(cli_unlink(cli->tree, fname))) {
1896                         printf("unlink of %s failed (%s)\n", 
1897                                fname, cli_errstr(cli->tree));
1898                         correct = False;
1899                 }
1900                 free(fname);
1901                 printf("%6d\r", i);
1902         }
1903         printf("%6d\n", 0);
1904
1905         printf("maxfid test finished\n");
1906         if (!torture_close_connection(cli)) {
1907                 correct = False;
1908         }
1909         return correct;
1910 }
1911
1912 /* send smb negprot commands, not reading the response */
1913 static BOOL run_negprot_nowait(int dummy)
1914 {
1915         int i;
1916         struct cli_state *cli;
1917         BOOL correct = True;
1918
1919         printf("starting negprot nowait test\n");
1920
1921         cli = open_nbt_connection();
1922         if (!cli) {
1923                 return False;
1924         }
1925
1926         printf("Establishing protocol negotiations - connect with another client\n");
1927
1928         for (i=0;i<50000;i++) {
1929                 smb_negprot_send(cli->transport, PROTOCOL_NT1);
1930         }
1931
1932         if (!torture_close_connection(cli)) {
1933                 correct = False;
1934         }
1935
1936         printf("finished negprot nowait test\n");
1937
1938         return correct;
1939 }
1940
1941
1942 /*
1943   This checks how the getatr calls works
1944 */
1945 static BOOL run_attrtest(int dummy)
1946 {
1947         struct cli_state *cli;
1948         int fnum;
1949         time_t t, t2;
1950         const char *fname = "\\attrib123456789.tst";
1951         BOOL correct = True;
1952
1953         printf("starting attrib test\n");
1954
1955         if (!torture_open_connection(&cli)) {
1956                 return False;
1957         }
1958
1959         cli_unlink(cli->tree, fname);
1960         fnum = cli_open(cli->tree, fname, 
1961                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1962         cli_close(cli->tree, fnum);
1963
1964         if (NT_STATUS_IS_ERR(cli_getatr(cli->tree, fname, NULL, NULL, &t))) {
1965                 printf("getatr failed (%s)\n", cli_errstr(cli->tree));
1966                 correct = False;
1967         }
1968
1969         printf("New file time is %s", ctime(&t));
1970
1971         if (abs(t - time(NULL)) > 60*60*24*10) {
1972                 printf("ERROR: SMBgetatr bug. time is %s",
1973                        ctime(&t));
1974                 t = time(NULL);
1975                 correct = False;
1976         }
1977
1978         t2 = t-60*60*24; /* 1 day ago */
1979
1980         printf("Setting file time to %s", ctime(&t2));
1981
1982         if (NT_STATUS_IS_ERR(cli_setatr(cli->tree, fname, 0, t2))) {
1983                 printf("setatr failed (%s)\n", cli_errstr(cli->tree));
1984                 correct = True;
1985         }
1986
1987         if (NT_STATUS_IS_ERR(cli_getatr(cli->tree, fname, NULL, NULL, &t))) {
1988                 printf("getatr failed (%s)\n", cli_errstr(cli->tree));
1989                 correct = True;
1990         }
1991
1992         printf("Retrieved file time as %s", ctime(&t));
1993
1994         if (t != t2) {
1995                 printf("ERROR: getatr/setatr bug. times are\n%s",
1996                        ctime(&t));
1997                 printf("%s", ctime(&t2));
1998                 correct = True;
1999         }
2000
2001         cli_unlink(cli->tree, fname);
2002
2003         if (!torture_close_connection(cli)) {
2004                 correct = False;
2005         }
2006
2007         printf("attrib test finished\n");
2008
2009         return correct;
2010 }
2011
2012
2013 /*
2014   This checks a couple of trans2 calls
2015 */
2016 static BOOL run_trans2test(int dummy)
2017 {
2018         struct cli_state *cli;
2019         int fnum;
2020         size_t size;
2021         time_t c_time, a_time, m_time, w_time, m_time2;
2022         const char *fname = "\\trans2.tst";
2023         const char *dname = "\\trans2";
2024         const char *fname2 = "\\trans2\\trans2.tst";
2025         const char *pname;
2026         BOOL correct = True;
2027
2028         printf("starting trans2 test\n");
2029
2030         if (!torture_open_connection(&cli)) {
2031                 return False;
2032         }
2033
2034         cli_unlink(cli->tree, fname);
2035
2036         printf("Testing qfileinfo\n");
2037         
2038         fnum = cli_open(cli->tree, fname, 
2039                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2040         if (NT_STATUS_IS_ERR(cli_qfileinfo(cli->tree, fnum, NULL, &size, &c_time, &a_time, &m_time,
2041                            NULL, NULL))) {
2042                 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(cli->tree));
2043                 correct = False;
2044         }
2045
2046         printf("Testing NAME_INFO\n");
2047
2048         if (NT_STATUS_IS_ERR(cli_qfilename(cli->tree, fnum, &pname))) {
2049                 printf("ERROR: qfilename failed (%s)\n", cli_errstr(cli->tree));
2050                 correct = False;
2051         }
2052
2053         if (!pname || strcmp(pname, fname)) {
2054                 printf("qfilename gave different name? [%s] [%s]\n",
2055                        fname, pname);
2056                 correct = False;
2057         }
2058
2059         cli_close(cli->tree, fnum);
2060         cli_unlink(cli->tree, fname);
2061
2062         fnum = cli_open(cli->tree, fname, 
2063                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2064         if (fnum == -1) {
2065                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli->tree));
2066                 return False;
2067         }
2068         cli_close(cli->tree, fnum);
2069
2070         printf("Checking for sticky create times\n");
2071
2072         if (NT_STATUS_IS_ERR(cli_qpathinfo(cli->tree, fname, &c_time, &a_time, &m_time, &size, NULL))) {
2073                 printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(cli->tree));
2074                 correct = False;
2075         } else {
2076                 if (c_time != m_time) {
2077                         printf("create time=%s", ctime(&c_time));
2078                         printf("modify time=%s", ctime(&m_time));
2079                         printf("This system appears to have sticky create times\n");
2080                 }
2081                 if (a_time % (60*60) == 0) {
2082                         printf("access time=%s", ctime(&a_time));
2083                         printf("This system appears to set a midnight access time\n");
2084                         correct = False;
2085                 }
2086
2087                 if (abs(m_time - time(NULL)) > 60*60*24*7) {
2088                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
2089                         correct = False;
2090                 }
2091         }
2092
2093
2094         cli_unlink(cli->tree, fname);
2095         fnum = cli_open(cli->tree, fname, 
2096                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2097         cli_close(cli->tree, fnum);
2098         if (NT_STATUS_IS_ERR(cli_qpathinfo2(cli->tree, fname, &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
2099                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(cli->tree));
2100                 correct = False;
2101         } else {
2102                 if (w_time < 60*60*24*2) {
2103                         printf("write time=%s", ctime(&w_time));
2104                         printf("This system appears to set a initial 0 write time\n");
2105                         correct = False;
2106                 }
2107         }
2108
2109         cli_unlink(cli->tree, fname);
2110
2111
2112         /* check if the server updates the directory modification time
2113            when creating a new file */
2114         if (NT_STATUS_IS_ERR(cli_mkdir(cli->tree, dname))) {
2115                 printf("ERROR: mkdir failed (%s)\n", cli_errstr(cli->tree));
2116                 correct = False;
2117         }
2118         sleep(3);
2119         if (NT_STATUS_IS_ERR(cli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
2120                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(cli->tree));
2121                 correct = False;
2122         }
2123
2124         fnum = cli_open(cli->tree, fname2, 
2125                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2126         cli_write(cli->tree, fnum,  0, (char *)&fnum, 0, sizeof(fnum));
2127         cli_close(cli->tree, fnum);
2128         if (NT_STATUS_IS_ERR(cli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time2, &w_time, &size, NULL, NULL))) {
2129                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(cli->tree));
2130                 correct = False;
2131         } else {
2132                 if (m_time2 == m_time) {
2133                         printf("This system does not update directory modification times\n");
2134                         correct = False;
2135                 }
2136         }
2137         cli_unlink(cli->tree, fname2);
2138         cli_rmdir(cli->tree, dname);
2139
2140         if (!torture_close_connection(cli)) {
2141                 correct = False;
2142         }
2143
2144         printf("trans2 test finished\n");
2145
2146         return correct;
2147 }
2148
2149 /*
2150   Test delete on close semantics.
2151  */
2152 static BOOL run_deletetest(int dummy)
2153 {
2154         struct cli_state *cli1;
2155         struct cli_state *cli2 = NULL;
2156         const char *fname = "\\delete.file";
2157         int fnum1 = -1;
2158         int fnum2 = -1;
2159         BOOL correct = True;
2160         
2161         printf("starting delete test\n");
2162         
2163         if (!torture_open_connection(&cli1)) {
2164                 return False;
2165         }
2166         
2167         /* Test 1 - this should delete the file on close. */
2168         
2169         cli_setatr(cli1->tree, fname, 0, 0);
2170         cli_unlink(cli1->tree, fname);
2171         
2172         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
2173                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 
2174                                    NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2175         
2176         if (fnum1 == -1) {
2177                 printf("[1] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2178                 correct = False;
2179                 goto fail;
2180         }
2181         
2182         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2183                 printf("[1] close failed (%s)\n", cli_errstr(cli1->tree));
2184                 correct = False;
2185                 goto fail;
2186         }
2187
2188         fnum1 = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
2189         if (fnum1 != -1) {
2190                 printf("[1] open of %s succeeded (should fail)\n", fname);
2191                 correct = False;
2192                 goto fail;
2193         }
2194         
2195         printf("first delete on close test succeeded.\n");
2196         
2197         /* Test 2 - this should delete the file on close. */
2198         
2199         cli_setatr(cli1->tree, fname, 0, 0);
2200         cli_unlink(cli1->tree, fname);
2201         
2202         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS,
2203                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, 
2204                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2205         
2206         if (fnum1 == -1) {
2207                 printf("[2] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2208                 correct = False;
2209                 goto fail;
2210         }
2211         
2212         if (NT_STATUS_IS_ERR(cli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2213                 printf("[2] setting delete_on_close failed (%s)\n", cli_errstr(cli1->tree));
2214                 correct = False;
2215                 goto fail;
2216         }
2217         
2218         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2219                 printf("[2] close failed (%s)\n", cli_errstr(cli1->tree));
2220                 correct = False;
2221                 goto fail;
2222         }
2223         
2224         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2225         if (fnum1 != -1) {
2226                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
2227                 if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2228                         printf("[2] close failed (%s)\n", cli_errstr(cli1->tree));
2229                         correct = False;
2230                         goto fail;
2231                 }
2232                 cli_unlink(cli1->tree, fname);
2233         } else
2234                 printf("second delete on close test succeeded.\n");
2235         
2236         /* Test 3 - ... */
2237         cli_setatr(cli1->tree, fname, 0, 0);
2238         cli_unlink(cli1->tree, fname);
2239
2240         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
2241                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2242
2243         if (fnum1 == -1) {
2244                 printf("[3] open - 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2245                 correct = False;
2246                 goto fail;
2247         }
2248
2249         /* This should fail with a sharing violation - open for delete is only compatible
2250            with SHARE_DELETE. */
2251
2252         fnum2 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
2253                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
2254                                    NTCREATEX_DISP_OPEN, 0, 0);
2255
2256         if (fnum2 != -1) {
2257                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
2258                 correct = False;
2259                 goto fail;
2260         }
2261
2262         /* This should succeed. */
2263
2264         fnum2 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
2265                         NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN, 0, 0);
2266
2267         if (fnum2 == -1) {
2268                 printf("[3] open  - 2 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2269                 correct = False;
2270                 goto fail;
2271         }
2272
2273         if (NT_STATUS_IS_ERR(cli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2274                 printf("[3] setting delete_on_close failed (%s)\n", cli_errstr(cli1->tree));
2275                 correct = False;
2276                 goto fail;
2277         }
2278         
2279         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2280                 printf("[3] close 1 failed (%s)\n", cli_errstr(cli1->tree));
2281                 correct = False;
2282                 goto fail;
2283         }
2284         
2285         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum2))) {
2286                 printf("[3] close 2 failed (%s)\n", cli_errstr(cli1->tree));
2287                 correct = False;
2288                 goto fail;
2289         }
2290         
2291         /* This should fail - file should no longer be there. */
2292
2293         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2294         if (fnum1 != -1) {
2295                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
2296                 if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2297                         printf("[3] close failed (%s)\n", cli_errstr(cli1->tree));
2298                 }
2299                 cli_unlink(cli1->tree, fname);
2300                 correct = False;
2301                 goto fail;
2302         } else
2303                 printf("third delete on close test succeeded.\n");
2304
2305         /* Test 4 ... */
2306         cli_setatr(cli1->tree, fname, 0, 0);
2307         cli_unlink(cli1->tree, fname);
2308
2309         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, 
2310                                    SA_RIGHT_FILE_READ_DATA  | 
2311                                    SA_RIGHT_FILE_WRITE_DATA |
2312                                    STD_RIGHT_DELETE_ACCESS,
2313                                    FILE_ATTRIBUTE_NORMAL, 
2314                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
2315                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2316                                                                 
2317         if (fnum1 == -1) {
2318                 printf("[4] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2319                 correct = False;
2320                 goto fail;
2321         }
2322
2323         /* This should succeed. */
2324         fnum2 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ,
2325                                    FILE_ATTRIBUTE_NORMAL, 
2326                                    NTCREATEX_SHARE_ACCESS_READ  | 
2327                                    NTCREATEX_SHARE_ACCESS_WRITE |
2328                                    NTCREATEX_SHARE_ACCESS_DELETE, 
2329                                    NTCREATEX_DISP_OPEN, 0, 0);
2330         if (fnum2 == -1) {
2331                 printf("[4] open  - 2 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2332                 correct = False;
2333                 goto fail;
2334         }
2335         
2336         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum2))) {
2337                 printf("[4] close - 1 failed (%s)\n", cli_errstr(cli1->tree));
2338                 correct = False;
2339                 goto fail;
2340         }
2341         
2342         if (NT_STATUS_IS_ERR(cli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2343                 printf("[4] setting delete_on_close failed (%s)\n", cli_errstr(cli1->tree));
2344                 correct = False;
2345                 goto fail;
2346         }
2347         
2348         /* This should fail - no more opens once delete on close set. */
2349         fnum2 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ,
2350                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
2351                                    NTCREATEX_DISP_OPEN, 0, 0);
2352         if (fnum2 != -1) {
2353                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
2354                 correct = False;
2355                 goto fail;
2356         } else
2357                 printf("fourth delete on close test succeeded.\n");
2358         
2359         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2360                 printf("[4] close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2361                 correct = False;
2362                 goto fail;
2363         }
2364         
2365         /* Test 5 ... */
2366         cli_setatr(cli1->tree, fname, 0, 0);
2367         cli_unlink(cli1->tree, fname);
2368         
2369         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2370         if (fnum1 == -1) {
2371                 printf("[5] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2372                 correct = False;
2373                 goto fail;
2374         }
2375
2376         /* This should fail - only allowed on NT opens with DELETE access. */
2377
2378         if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2379                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
2380                 correct = False;
2381                 goto fail;
2382         }
2383
2384         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2385                 printf("[5] close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2386                 correct = False;
2387                 goto fail;
2388         }
2389         
2390         printf("fifth delete on close test succeeded.\n");
2391         
2392         /* Test 6 ... */
2393         cli_setatr(cli1->tree, fname, 0, 0);
2394         cli_unlink(cli1->tree, fname);
2395         
2396         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, 
2397                                    SA_RIGHT_FILE_READ_DATA | SA_RIGHT_FILE_WRITE_DATA,
2398                                    FILE_ATTRIBUTE_NORMAL, 
2399                                    NTCREATEX_SHARE_ACCESS_READ  |
2400                                    NTCREATEX_SHARE_ACCESS_WRITE |
2401                                    NTCREATEX_SHARE_ACCESS_DELETE,
2402                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2403         
2404         if (fnum1 == -1) {
2405                 printf("[6] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2406                 correct = False;
2407                 goto fail;
2408         }
2409         
2410         /* This should fail - only allowed on NT opens with DELETE access. */
2411         
2412         if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2413                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
2414                 correct = False;
2415                 goto fail;
2416         }
2417
2418         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2419                 printf("[6] close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2420                 correct = False;
2421                 goto fail;
2422         }
2423
2424         printf("sixth delete on close test succeeded.\n");
2425         
2426         /* Test 7 ... */
2427         cli_setatr(cli1->tree, fname, 0, 0);
2428         cli_unlink(cli1->tree, fname);
2429         
2430         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, 
2431                                    SA_RIGHT_FILE_READ_DATA  | 
2432                                    SA_RIGHT_FILE_WRITE_DATA |
2433                                    STD_RIGHT_DELETE_ACCESS,
2434                                    FILE_ATTRIBUTE_NORMAL, 0, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2435                                                                 
2436         if (fnum1 == -1) {
2437                 printf("[7] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2438                 correct = False;
2439                 goto fail;
2440         }
2441
2442         if (NT_STATUS_IS_ERR(cli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2443                 printf("[7] setting delete_on_close on file failed !\n");
2444                 correct = False;
2445                 goto fail;
2446         }
2447         
2448         if (NT_STATUS_IS_ERR(cli_nt_delete_on_close(cli1->tree, fnum1, False))) {
2449                 printf("[7] unsetting delete_on_close on file failed !\n");
2450                 correct = False;
2451                 goto fail;
2452         }
2453
2454         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2455                 printf("[7] close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2456                 correct = False;
2457                 goto fail;
2458         }
2459         
2460         /* This next open should succeed - we reset the flag. */
2461         
2462         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2463         if (fnum1 == -1) {
2464                 printf("[5] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2465                 correct = False;
2466                 goto fail;
2467         }
2468
2469         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2470                 printf("[7] close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2471                 correct = False;
2472                 goto fail;
2473         }
2474
2475         printf("seventh delete on close test succeeded.\n");
2476         
2477         /* Test 7 ... */
2478         cli_setatr(cli1->tree, fname, 0, 0);
2479         cli_unlink(cli1->tree, fname);
2480         
2481         if (!torture_open_connection(&cli2)) {
2482                 printf("[8] failed to open second connection.\n");
2483                 correct = False;
2484                 goto fail;
2485         }
2486
2487         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|STD_RIGHT_DELETE_ACCESS,
2488                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
2489                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2490         
2491         if (fnum1 == -1) {
2492                 printf("[8] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2493                 correct = False;
2494                 goto fail;
2495         }
2496
2497         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|STD_RIGHT_DELETE_ACCESS,
2498                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
2499                                    NTCREATEX_DISP_OPEN, 0, 0);
2500         
2501         if (fnum2 == -1) {
2502                 printf("[8] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2503                 correct = False;
2504                 goto fail;
2505         }
2506
2507         if (NT_STATUS_IS_ERR(cli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2508                 printf("[8] setting delete_on_close on file failed !\n");
2509                 correct = False;
2510                 goto fail;
2511         }
2512         
2513         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2514                 printf("[8] close - 1 failed (%s)\n", cli_errstr(cli1->tree));
2515                 correct = False;
2516                 goto fail;
2517         }
2518
2519         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum2))) {
2520                 printf("[8] close - 2 failed (%s)\n", cli_errstr(cli2->tree));
2521                 correct = False;
2522                 goto fail;
2523         }
2524
2525         /* This should fail.. */
2526         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2527         if (fnum1 != -1) {
2528                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
2529                 goto fail;
2530                 correct = False;
2531         } else
2532                 printf("eighth delete on close test succeeded.\n");
2533
2534         /* This should fail - we need to set DELETE_ACCESS. */
2535         fnum1 = cli_nt_create_full(cli1->tree, fname, 0,SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA,
2536                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2537         
2538         if (fnum1 != -1) {
2539                 printf("[9] open of %s succeeded should have failed!\n", fname);
2540                 correct = False;
2541                 goto fail;
2542         }
2543
2544         printf("ninth delete on close test succeeded.\n");
2545
2546         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|STD_RIGHT_DELETE_ACCESS,
2547                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2548         if (fnum1 == -1) {
2549                 printf("[10] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2550                 correct = False;
2551                 goto fail;
2552         }
2553
2554         /* This should delete the file. */
2555         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2556                 printf("[10] close failed (%s)\n", cli_errstr(cli1->tree));
2557                 correct = False;
2558                 goto fail;
2559         }
2560
2561         /* This should fail.. */
2562         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2563         if (fnum1 != -1) {
2564                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
2565                 goto fail;
2566                 correct = False;
2567         } else
2568                 printf("tenth delete on close test succeeded.\n");
2569         printf("finished delete test\n");
2570
2571   fail:
2572         /* FIXME: This will crash if we aborted before cli2 got
2573          * intialized, because these functions don't handle
2574          * uninitialized connections. */
2575                 
2576         cli_close(cli1->tree, fnum1);
2577         cli_close(cli1->tree, fnum2);
2578         cli_setatr(cli1->tree, fname, 0, 0);
2579         cli_unlink(cli1->tree, fname);
2580
2581         if (!torture_close_connection(cli1)) {
2582                 correct = False;
2583         }
2584         if (!torture_close_connection(cli2)) {
2585                 correct = False;
2586         }
2587         return correct;
2588 }
2589
2590
2591 /*
2592   print out server properties
2593  */
2594 static BOOL run_properties(int dummy)
2595 {
2596         struct cli_state *cli;
2597         BOOL correct = True;
2598         
2599         printf("starting properties test\n");
2600         
2601         ZERO_STRUCT(cli);
2602
2603         if (!torture_open_connection(&cli)) {
2604                 return False;
2605         }
2606         
2607         d_printf("Capabilities 0x%08x\n", cli->transport->negotiate.capabilities);
2608
2609         if (!torture_close_connection(cli)) {
2610                 correct = False;
2611         }
2612
2613         return correct;
2614 }
2615
2616
2617
2618 /* FIRST_DESIRED_ACCESS   0xf019f */
2619 #define FIRST_DESIRED_ACCESS   SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|SA_RIGHT_FILE_APPEND_DATA|\
2620                                SA_RIGHT_FILE_READ_EA|                           /* 0xf */ \
2621                                SA_RIGHT_FILE_WRITE_EA|SA_RIGHT_FILE_READ_ATTRIBUTES|     /* 0x90 */ \
2622                                SA_RIGHT_FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
2623                                STD_RIGHT_DELETE_ACCESS|STD_RIGHT_READ_CONTROL_ACCESS|\
2624                                STD_RIGHT_WRITE_DAC_ACCESS|STD_RIGHT_WRITE_OWNER_ACCESS     /* 0xf0000 */
2625 /* SECOND_DESIRED_ACCESS  0xe0080 */
2626 #define SECOND_DESIRED_ACCESS  SA_RIGHT_FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
2627                                STD_RIGHT_READ_CONTROL_ACCESS|STD_RIGHT_WRITE_DAC_ACCESS|\
2628                                STD_RIGHT_WRITE_OWNER_ACCESS                      /* 0xe0000 */
2629
2630 #if 0
2631 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
2632                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
2633                                SA_RIGHT_FILE_READ_DATA|\
2634                                WRITE_OWNER_ACCESS                      /* */
2635 #endif
2636
2637 /*
2638   Test ntcreate calls made by xcopy
2639  */
2640 static BOOL run_xcopy(int dummy)
2641 {
2642         struct cli_state *cli1;
2643         const char *fname = "\\test.txt";
2644         BOOL correct = True;
2645         int fnum1, fnum2;
2646
2647         printf("starting xcopy test\n");
2648         
2649         if (!torture_open_connection(&cli1)) {
2650                 return False;
2651         }
2652         
2653         fnum1 = cli_nt_create_full(cli1->tree, fname, 0,
2654                                    FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
2655                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 
2656                                    0x4044, 0);
2657
2658         if (fnum1 == -1) {
2659                 printf("First open failed - %s\n", cli_errstr(cli1->tree));
2660                 return False;
2661         }
2662
2663         fnum2 = cli_nt_create_full(cli1->tree, fname, 0,
2664                                    SECOND_DESIRED_ACCESS, 0,
2665                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN, 
2666                                    0x200000, 0);
2667         if (fnum2 == -1) {
2668                 printf("second open failed - %s\n", cli_errstr(cli1->tree));
2669                 return False;
2670         }
2671         
2672         if (!torture_close_connection(cli1)) {
2673                 correct = False;
2674         }
2675         
2676         return correct;
2677 }
2678
2679 /*
2680   Test rename on files open with share delete and no share delete.
2681  */
2682 static BOOL run_rename(int dummy)
2683 {
2684         struct cli_state *cli1;
2685         const char *fname = "\\test.txt";
2686         const char *fname1 = "\\test1.txt";
2687         BOOL correct = True;
2688         int fnum1;
2689
2690         printf("starting rename test\n");
2691         
2692         if (!torture_open_connection(&cli1)) {
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                                    NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2700
2701         if (fnum1 == -1) {
2702                 printf("First open failed - %s\n", cli_errstr(cli1->tree));
2703                 return False;
2704         }
2705
2706         if (NT_STATUS_IS_ERR(cli_rename(cli1->tree, fname, fname1))) {
2707                 printf("First rename failed (this is correct) - %s\n", cli_errstr(cli1->tree));
2708         } else {
2709                 printf("First rename succeeded - this should have failed !\n");
2710                 correct = False;
2711         }
2712
2713         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2714                 printf("close - 1 failed (%s)\n", cli_errstr(cli1->tree));
2715                 return False;
2716         }
2717
2718         cli_unlink(cli1->tree, fname);
2719         cli_unlink(cli1->tree, fname1);
2720         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
2721 #if 0
2722                                    NTCREATEX_SHARE_ACCESS_DELETE|NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2723 #else
2724                                    NTCREATEX_SHARE_ACCESS_DELETE|NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2725 #endif
2726
2727         if (fnum1 == -1) {
2728                 printf("Second open failed - %s\n", cli_errstr(cli1->tree));
2729                 return False;
2730         }
2731
2732         if (NT_STATUS_IS_ERR(cli_rename(cli1->tree, fname, fname1))) {
2733                 printf("Second rename failed - this should have succeeded - %s\n", cli_errstr(cli1->tree));
2734                 correct = False;
2735         } else {
2736                 printf("Second rename succeeded\n");
2737         }
2738
2739         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2740                 printf("close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2741                 return False;
2742         }
2743
2744         cli_unlink(cli1->tree, fname);
2745         cli_unlink(cli1->tree, fname1);
2746
2747         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_READ_CONTROL_ACCESS, FILE_ATTRIBUTE_NORMAL,
2748                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2749
2750         if (fnum1 == -1) {
2751                 printf("Third open failed - %s\n", cli_errstr(cli1->tree));
2752                 return False;
2753         }
2754
2755
2756 #if 0
2757   {
2758   int fnum2;
2759
2760         fnum2 = cli_nt_create_full(cli1->tree, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
2761                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2762
2763         if (fnum2 == -1) {
2764                 printf("Fourth open failed - %s\n", cli_errstr(cli1->tree));
2765                 return False;
2766         }
2767         if (!cli_nt_delete_on_close(cli1->tree, fnum2, True)) {
2768                 printf("[8] setting delete_on_close on file failed !\n");
2769                 return False;
2770         }
2771         
2772         if (!cli_close(cli1->tree, fnum2)) {
2773                 printf("close - 4 failed (%s)\n", cli_errstr(cli1->tree));
2774                 return False;
2775         }
2776   }
2777 #endif
2778
2779         if (NT_STATUS_IS_ERR(cli_rename(cli1->tree, fname, fname1))) {
2780                 printf("Third rename failed - this should have succeeded - %s\n", cli_errstr(cli1->tree));
2781                 correct = False;
2782         } else {
2783                 printf("Third rename succeeded\n");
2784         }
2785
2786         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2787                 printf("close - 3 failed (%s)\n", cli_errstr(cli1->tree));
2788                 return False;
2789         }
2790
2791         cli_unlink(cli1->tree, fname);
2792         cli_unlink(cli1->tree, fname1);
2793
2794         if (!torture_close_connection(cli1)) {
2795                 correct = False;
2796         }
2797         
2798         return correct;
2799 }
2800
2801 static BOOL run_pipe_number(int dummy)
2802 {
2803         struct cli_state *cli1;
2804         const char *pipe_name = "\\WKSSVC";
2805         int fnum;
2806         int num_pipes = 0;
2807
2808         printf("starting pipenumber test\n");
2809         if (!torture_open_connection(&cli1)) {
2810                 return False;
2811         }
2812
2813         while(1) {
2814                 fnum = cli_nt_create_full(cli1->tree, pipe_name, 0, SA_RIGHT_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
2815                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OPEN_IF, 0, 0);
2816
2817                 if (fnum == -1) {
2818                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, cli_errstr(cli1->tree));
2819                         break;
2820                 }
2821                 num_pipes++;
2822         }
2823
2824         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
2825         torture_close_connection(cli1);
2826         return True;
2827 }
2828
2829
2830 /*
2831   Test open mode returns on read-only files.
2832  */
2833  static BOOL run_opentest(int dummy)
2834 {
2835         static struct cli_state *cli1;
2836         static struct cli_state *cli2;
2837         const char *fname = "\\readonly.file";
2838         int fnum1, fnum2;
2839         char buf[20];
2840         size_t fsize;
2841         BOOL correct = True;
2842         char *tmp_path;
2843         int failures = 0;
2844
2845         printf("starting open test\n");
2846         
2847         if (!torture_open_connection(&cli1)) {
2848                 return False;
2849         }
2850         
2851         cli_setatr(cli1->tree, fname, 0, 0);
2852         cli_unlink(cli1->tree, fname);
2853         
2854         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
2855         if (fnum1 == -1) {
2856                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2857                 return False;
2858         }
2859
2860         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2861                 printf("close2 failed (%s)\n", cli_errstr(cli1->tree));
2862                 return False;
2863         }
2864         
2865         if (NT_STATUS_IS_ERR(cli_setatr(cli1->tree, fname, FILE_ATTRIBUTE_READONLY, 0))) {
2866                 printf("cli_setatr failed (%s)\n", cli_errstr(cli1->tree));
2867                 CHECK_MAX_FAILURES(error_test1);
2868                 return False;
2869         }
2870         
2871         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
2872         if (fnum1 == -1) {
2873                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2874                 CHECK_MAX_FAILURES(error_test1);
2875                 return False;
2876         }
2877         
2878         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
2879         fnum2 = cli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
2880         
2881         if (check_error(__LINE__, cli1, ERRDOS, ERRnoaccess, 
2882                         NT_STATUS_ACCESS_DENIED)) {
2883                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
2884         }
2885         
2886         printf("finished open test 1\n");
2887 error_test1:
2888         cli_close(cli1->tree, fnum1);
2889         
2890         /* Now try not readonly and ensure ERRbadshare is returned. */
2891         
2892         cli_setatr(cli1->tree, fname, 0, 0);
2893         
2894         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
2895         if (fnum1 == -1) {
2896                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2897                 return False;
2898         }
2899         
2900         /* This will fail - but the error should be ERRshare. */
2901         fnum2 = cli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
2902         
2903         if (check_error(__LINE__, cli1, ERRDOS, ERRbadshare, 
2904                         NT_STATUS_SHARING_VIOLATION)) {
2905                 printf("correct error code ERRDOS/ERRbadshare returned\n");
2906         }
2907         
2908         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2909                 printf("close2 failed (%s)\n", cli_errstr(cli1->tree));
2910                 return False;
2911         }
2912         
2913         cli_unlink(cli1->tree, fname);
2914         
2915         printf("finished open test 2\n");
2916         
2917         /* Test truncate open disposition on file opened for read. */
2918         
2919         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
2920         if (fnum1 == -1) {
2921                 printf("(3) open (1) of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2922                 return False;
2923         }
2924         
2925         /* write 20 bytes. */
2926         
2927         memset(buf, '\0', 20);
2928
2929         if (cli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
2930                 printf("write failed (%s)\n", cli_errstr(cli1->tree));
2931                 correct = False;
2932         }
2933
2934         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2935                 printf("(3) close1 failed (%s)\n", cli_errstr(cli1->tree));
2936                 return False;
2937         }
2938         
2939         /* Ensure size == 20. */
2940         if (NT_STATUS_IS_ERR(cli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
2941                 printf("(3) getatr failed (%s)\n", cli_errstr(cli1->tree));
2942                 CHECK_MAX_FAILURES(error_test3);
2943                 return False;
2944         }
2945         
2946         if (fsize != 20) {
2947                 printf("(3) file size != 20\n");
2948                 CHECK_MAX_FAILURES(error_test3);
2949                 return False;
2950         }
2951
2952         /* Now test if we can truncate a file opened for readonly. */
2953         
2954         fnum1 = cli_open(cli1->tree, fname, O_RDONLY|O_TRUNC, DENY_NONE);
2955         if (fnum1 == -1) {
2956                 printf("(3) open (2) of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2957                 CHECK_MAX_FAILURES(error_test3);
2958                 return False;
2959         }
2960         
2961         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2962                 printf("close2 failed (%s)\n", cli_errstr(cli1->tree));
2963                 return False;
2964         }
2965
2966         /* Ensure size == 0. */
2967         if (NT_STATUS_IS_ERR(cli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
2968                 printf("(3) getatr failed (%s)\n", cli_errstr(cli1->tree));
2969                 CHECK_MAX_FAILURES(error_test3);
2970                 return False;
2971         }
2972
2973         if (fsize != 0) {
2974                 printf("(3) file size != 0\n");
2975                 CHECK_MAX_FAILURES(error_test3);
2976                 return False;
2977         }
2978         printf("finished open test 3\n");
2979 error_test3:    
2980         cli_unlink(cli1->tree, fname);
2981
2982
2983         printf("testing ctemp\n");
2984         fnum1 = cli_ctemp(cli1->tree, "\\", &tmp_path);
2985         if (fnum1 == -1) {
2986                 printf("ctemp failed (%s)\n", cli_errstr(cli1->tree));
2987                 CHECK_MAX_FAILURES(error_test4);
2988                 return False;
2989         }
2990         printf("ctemp gave path %s\n", tmp_path);
2991         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2992                 printf("close of temp failed (%s)\n", cli_errstr(cli1->tree));
2993         }
2994         if (NT_STATUS_IS_ERR(cli_unlink(cli1->tree, tmp_path))) {
2995                 printf("unlink of temp failed (%s)\n", cli_errstr(cli1->tree));
2996         }
2997 error_test4:    
2998         /* Test the non-io opens... */
2999
3000         if (!torture_open_connection(&cli2)) {
3001                 return False;
3002         }
3003         
3004         cli_setatr(cli2->tree, fname, 0, 0);
3005         cli_unlink(cli2->tree, fname);
3006         
3007         printf("TEST #1 testing 2 non-io opens (no delete)\n");
3008         
3009         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3010                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3011
3012         if (fnum1 == -1) {
3013                 printf("test 1 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3014                 CHECK_MAX_FAILURES(error_test10);
3015                 return False;
3016         }
3017
3018         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3019                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3020         if (fnum2 == -1) {
3021                 printf("test 1 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3022                 CHECK_MAX_FAILURES(error_test10);
3023                 return False;
3024         }
3025
3026         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3027                 printf("test 1 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3028                 return False;
3029         }
3030         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum2))) {
3031                 printf("test 1 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3032                 return False;
3033         }
3034
3035         printf("non-io open test #1 passed.\n");
3036 error_test10:
3037         cli_unlink(cli1->tree, fname);
3038
3039         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
3040         
3041         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3042                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3043
3044         if (fnum1 == -1) {
3045                 printf("test 2 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3046                 CHECK_MAX_FAILURES(error_test20);
3047                 return False;
3048         }
3049
3050         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3051                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3052
3053         if (fnum2 == -1) {
3054                 printf("test 2 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3055                 CHECK_MAX_FAILURES(error_test20);
3056                 return False;
3057         }
3058
3059         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3060                 printf("test 1 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3061                 return False;
3062         }
3063         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum2))) {
3064                 printf("test 1 close 2 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3065                 return False;
3066         }
3067
3068         printf("non-io open test #2 passed.\n");
3069 error_test20:
3070         cli_unlink(cli1->tree, fname);
3071
3072         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
3073         
3074         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3075                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3076
3077         if (fnum1 == -1) {
3078                 printf("test 3 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3079                 CHECK_MAX_FAILURES(error_test30);
3080                 return False;
3081         }
3082
3083         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3084                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3085
3086         if (fnum2 == -1) {
3087                 printf("test 3 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3088                 CHECK_MAX_FAILURES(error_test30);
3089                 return False;
3090         }
3091
3092         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3093                 printf("test 3 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3094                 return False;
3095         }
3096         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum2))) {
3097                 printf("test 3 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3098                 return False;
3099         }
3100
3101         printf("non-io open test #3 passed.\n");
3102 error_test30:
3103         cli_unlink(cli1->tree, fname);
3104
3105         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
3106         
3107         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|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 4 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3112                 CHECK_MAX_FAILURES(error_test40);
3113                 return False;
3114         }
3115
3116         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3117                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3118
3119         if (fnum2 != -1) {
3120                 printf("test 4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, cli_errstr(cli2->tree));
3121                 CHECK_MAX_FAILURES(error_test40);
3122                 return False;
3123         }
3124
3125         printf("test 4 open 2 of %s gave %s (correct error should be %s)\n", fname, cli_errstr(cli2->tree), "sharing violation");
3126
3127         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3128                 printf("test 4 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3129                 return False;
3130         }
3131
3132         printf("non-io open test #4 passed.\n");
3133 error_test40:
3134         cli_unlink(cli1->tree, fname);
3135
3136         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
3137         
3138         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3139                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3140
3141         if (fnum1 == -1) {
3142                 printf("test 5 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3143                 CHECK_MAX_FAILURES(error_test50);
3144                 return False;
3145         }
3146
3147         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3148                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3149
3150         if (fnum2 == -1) {
3151                 printf("test 5 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3152                 CHECK_MAX_FAILURES(error_test50);
3153                 return False;
3154         }
3155
3156         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3157                 printf("test 5 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3158                 return False;
3159         }
3160
3161         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum2))) {
3162                 printf("test 5 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3163                 return False;
3164         }
3165
3166         printf("non-io open test #5 passed.\n");
3167 error_test50:
3168         printf("TEST #6 testing 1 non-io open, one io open\n");
3169         
3170         cli_unlink(cli1->tree, fname);
3171
3172         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
3173                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3174
3175         if (fnum1 == -1) {
3176                 printf("test 6 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3177                 CHECK_MAX_FAILURES(error_test60);
3178                 return False;
3179         }
3180
3181         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3182                                    NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OPEN_IF, 0, 0);
3183
3184         if (fnum2 == -1) {
3185                 printf("test 6 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3186                 CHECK_MAX_FAILURES(error_test60);
3187                 return False;
3188         }
3189
3190         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3191                 printf("test 6 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3192                 return False;
3193         }
3194
3195         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum2))) {
3196                 printf("test 6 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3197                 return False;
3198         }
3199
3200         printf("non-io open test #6 passed.\n");
3201 error_test60:
3202         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
3203
3204         cli_unlink(cli1->tree, fname);
3205
3206         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
3207                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3208
3209         if (fnum1 == -1) {
3210                 printf("test 7 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3211                 CHECK_MAX_FAILURES(error_test70);
3212                 return False;
3213         }
3214
3215         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3216                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3217
3218         if (fnum2 != -1) {
3219                 printf("test 7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, cli_errstr(cli2->tree));
3220                 CHECK_MAX_FAILURES(error_test70);
3221                 return False;
3222         }
3223
3224         printf("test 7 open 2 of %s gave %s (correct error should be %s)\n", fname, cli_errstr(cli2->tree), "sharing violation");
3225
3226         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3227                 printf("test 7 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3228                 return False;
3229         }
3230
3231         printf("non-io open test #7 passed.\n");
3232 error_test70:
3233         cli_unlink(cli1->tree, fname);
3234
3235         if (!torture_close_connection(cli1)) {
3236                 correct = False;
3237         }
3238         if (!torture_close_connection(cli2)) {
3239                 correct = False;
3240         }
3241         
3242         return correct;
3243 }
3244
3245
3246 static uint32 open_attrs_table[] = {
3247                 FILE_ATTRIBUTE_NORMAL,
3248                 FILE_ATTRIBUTE_ARCHIVE,
3249                 FILE_ATTRIBUTE_READONLY,
3250                 FILE_ATTRIBUTE_HIDDEN,
3251                 FILE_ATTRIBUTE_SYSTEM,
3252
3253                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
3254                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
3255                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
3256                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
3257                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
3258                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
3259
3260                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
3261                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
3262                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
3263                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
3264 };
3265
3266 struct trunc_open_results {
3267         unsigned int num;
3268         uint32 init_attr;
3269         uint32 trunc_attr;
3270         uint32 result_attr;
3271 };
3272
3273 static struct trunc_open_results attr_results[] = {
3274         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
3275         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
3276         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
3277         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
3278         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
3279         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
3280         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3281         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3282         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
3283         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3284         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3285         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
3286         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3287         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3288         { 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 },
3289         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3290         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3291         { 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 },
3292         { 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 },
3293         { 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 },
3294         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3295         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3296         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
3297         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3298         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3299         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
3300 };
3301
3302 static BOOL run_openattrtest(int dummy)
3303 {
3304         struct cli_state *cli1;
3305         const char *fname = "\\openattr.file";
3306         int fnum1;
3307         BOOL correct = True;
3308         uint16 attr;
3309         unsigned int i, j, k, l;
3310         int failures = 0;
3311
3312         printf("starting open attr test\n");
3313         
3314         if (!torture_open_connection(&cli1)) {
3315                 return False;
3316         }
3317         
3318         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
3319                 cli_setatr(cli1->tree, fname, 0, 0);
3320                 cli_unlink(cli1->tree, fname);
3321                 fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_WRITE_DATA, open_attrs_table[i],
3322                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3323
3324                 if (fnum1 == -1) {
3325                         printf("open %d (1) of %s failed (%s)\n", i, fname, cli_errstr(cli1->tree));
3326                         return False;
3327                 }
3328
3329                 if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3330                         printf("close %d (1) of %s failed (%s)\n", i, fname, cli_errstr(cli1->tree));
3331                         return False;
3332                 }
3333
3334                 for (j = 0; j < ARRAY_SIZE(open_attrs_table); j++) {
3335                         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, 
3336                                                    SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA, 
3337                                                    open_attrs_table[j],
3338                                                    NTCREATEX_SHARE_ACCESS_NONE, 
3339                                                    NTCREATEX_DISP_OVERWRITE, 0, 0);
3340
3341                         if (fnum1 == -1) {
3342                                 for (l = 0; l < ARRAY_SIZE(attr_results); l++) {
3343                                         if (attr_results[l].num == k) {
3344                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
3345                                                                 k, open_attrs_table[i],
3346                                                                 open_attrs_table[j],
3347                                                                 fname, NT_STATUS_V(cli_nt_error(cli1->tree)), cli_errstr(cli1->tree));
3348                                                 correct = False;
3349                                                 CHECK_MAX_FAILURES(error_exit);
3350                                         }