393ac9c56b1c6eb89919f4c63e7eb777b766a73a
[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 (!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 (!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 (!cli_close(c->tree, fnum)) {
277                         printf("close failed (%s)\n", cli_errstr(c->tree));
278                         correct = False;
279                 }
280
281                 if (!cli_unlink(c->tree, fname)) {
282                         printf("unlink failed (%s)\n", cli_errstr(c->tree));
283                         correct = False;
284                 }
285
286                 if (!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 (!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 (!cli_close(c2->tree, fnum2)) {
482                 printf("close failed (%s)\n", cli_errstr(c2->tree));
483                 correct = False;
484         }
485         if (!cli_close(c1->tree, fnum1)) {
486                 printf("close failed (%s)\n", cli_errstr(c1->tree));
487                 correct = False;
488         }
489
490         if (!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 (!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 (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 (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 (!cli_close(cli1->tree, fnum2)) {
740                 printf("close1 failed (%s)\n", cli_errstr(cli1->tree));
741                 return False;
742         }
743
744         if (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 (!cli_close(cli1->tree, fnum1)) {
753                 printf("close2 failed (%s)\n", cli_errstr(cli1->tree));
754                 return False;
755         }
756
757         if (!cli_close(cli2->tree, fnum3)) {
758                 printf("close3 failed (%s)\n", cli_errstr(cli2->tree));
759                 return False;
760         }
761
762         if (!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 (!cli_send_tconX(cli, share, "?????",
825                             password)) {
826                 printf("%s refused 2nd tree connect (%s)\n", host,
827                            cli_errstr(cli->tree));
828                 cli_shutdown(cli);
829                 return False;
830         }
831
832         cnum2 = cli->tree->tid;
833         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
834         vuid2 = cli->session->vuid + 1;
835
836         /* try a write with the wrong tid */
837         cli->tree->tid = cnum2;
838
839         if (cli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
840                 printf("* server allows write with wrong TID\n");
841                 ret = False;
842         } else {
843                 printf("server fails write with wrong TID : %s\n", cli_errstr(cli->tree));
844         }
845
846
847         /* try a write with an invalid tid */
848         cli->tree->tid = cnum3;
849
850         if (cli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
851                 printf("* server allows write with invalid TID\n");
852                 ret = False;
853         } else {
854                 printf("server fails write with invalid TID : %s\n", cli_errstr(cli->tree));
855         }
856
857         /* try a write with an invalid vuid */
858         cli->session->vuid = vuid2;
859         cli->tree->tid = cnum1;
860
861         if (cli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
862                 printf("* server allows write with invalid VUID\n");
863                 ret = False;
864         } else {
865                 printf("server fails write with invalid VUID : %s\n", cli_errstr(cli->tree));
866         }
867
868         cli->session->vuid = vuid1;
869         cli->tree->tid = cnum1;
870
871         if (!cli_close(cli->tree, fnum1)) {
872                 printf("close failed (%s)\n", cli_errstr(cli->tree));
873                 return False;
874         }
875
876         cli->tree->tid = cnum2;
877
878         if (!cli_tdis(cli)) {
879                 printf("secondary tdis failed (%s)\n", cli_errstr(cli->tree));
880                 return False;
881         }
882
883         cli->tree = tree1;  /* restore initial tree */
884         cli->tree->tid = cnum1;
885
886         if (!torture_close_connection(cli)) {
887                 return False;
888         }
889
890         return ret;
891 }
892
893
894
895 static BOOL tcon_devtest(struct cli_state *cli,
896                          const char *myshare, const char *devtype,
897                          NTSTATUS expected_error)
898 {
899         BOOL status;
900         BOOL ret;
901         char *password = lp_parm_string(-1, "torture", "password");
902
903         status = cli_send_tconX(cli, myshare, devtype,
904                                 password);
905
906         printf("Trying share %s with devtype %s\n", myshare, devtype);
907
908         if (NT_STATUS_IS_OK(expected_error)) {
909                 if (status) {
910                         ret = True;
911                 } else {
912                         printf("tconX to share %s with type %s "
913                                "should have succeeded but failed\n",
914                                myshare, devtype);
915                         ret = False;
916                 }
917                 cli_tdis(cli);
918         } else {
919                 if (status) {
920                         printf("tconx to share %s with type %s "
921                                "should have failed but succeeded\n",
922                                myshare, devtype);
923                         ret = False;
924                 } else {
925                         if (NT_STATUS_EQUAL(cli_nt_error(cli->tree),
926                                             expected_error)) {
927                                 ret = True;
928                         } else {
929                                 printf("Returned unexpected error\n");
930                                 ret = False;
931                         }
932                 }
933         }
934         return ret;
935 }
936
937 /*
938  checks for correct tconX support
939  */
940 static BOOL run_tcon_devtype_test(int dummy)
941 {
942         struct cli_state *cli1 = NULL;
943         BOOL retry;
944         int flags = 0;
945         NTSTATUS status;
946         BOOL ret = True;
947         char *host = lp_parm_string(-1, "torture", "host");
948         char *share = lp_parm_string(-1, "torture", "share");
949         char *username = lp_parm_string(-1, "torture", "username");
950         char *password = lp_parm_string(-1, "torture", "password");
951         
952         status = cli_full_connection(&cli1, lp_netbios_name(),
953                                      host, NULL, 
954                                      share, "?????",
955                                      username, lp_workgroup(),
956                                      password, flags, &retry);
957
958         if (!NT_STATUS_IS_OK(status)) {
959                 printf("could not open connection\n");
960                 return False;
961         }
962
963         if (!tcon_devtest(cli1, "IPC$", "A:", NT_STATUS_BAD_DEVICE_TYPE))
964                 ret = False;
965
966         if (!tcon_devtest(cli1, "IPC$", "?????", NT_STATUS_OK))
967                 ret = False;
968
969         if (!tcon_devtest(cli1, "IPC$", "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
970                 ret = False;
971
972         if (!tcon_devtest(cli1, "IPC$", "IPC", NT_STATUS_OK))
973                 ret = False;
974                         
975         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
976                 ret = False;
977
978         if (!tcon_devtest(cli1, share, "A:", NT_STATUS_OK))
979                 ret = False;
980
981         if (!tcon_devtest(cli1, share, "?????", NT_STATUS_OK))
982                 ret = False;
983
984         if (!tcon_devtest(cli1, share, "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
985                 ret = False;
986
987         if (!tcon_devtest(cli1, share, "IPC", NT_STATUS_BAD_DEVICE_TYPE))
988                 ret = False;
989                         
990         if (!tcon_devtest(cli1, share, "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
991                 ret = False;
992
993         cli_shutdown(cli1);
994
995         if (ret)
996                 printf("Passed tcondevtest\n");
997
998         return ret;
999 }
1000
1001
1002 /*
1003   This test checks that 
1004
1005   1) the server supports multiple locking contexts on the one SMB
1006   connection, distinguished by PID.  
1007
1008   2) the server correctly fails overlapping locks made by the same PID (this
1009      goes against POSIX behaviour, which is why it is tricky to implement)
1010
1011   3) the server denies unlock requests by an incorrect client PID
1012 */
1013 static BOOL run_locktest2(int dummy)
1014 {
1015         struct cli_state *cli;
1016         const char *fname = "\\lockt2.lck";
1017         int fnum1, fnum2, fnum3;
1018         BOOL correct = True;
1019
1020         if (!torture_open_connection(&cli)) {
1021                 return False;
1022         }
1023
1024         printf("starting locktest2\n");
1025
1026         cli_unlink(cli->tree, fname);
1027
1028         printf("Testing pid context\n");
1029         
1030         cli->session->pid = 1;
1031
1032         fnum1 = cli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1033         if (fnum1 == -1) {
1034                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli->tree));
1035                 return False;
1036         }
1037
1038         fnum2 = cli_open(cli->tree, fname, O_RDWR, DENY_NONE);
1039         if (fnum2 == -1) {
1040                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(cli->tree));
1041                 return False;
1042         }
1043
1044         cli->session->pid = 2;
1045
1046         fnum3 = cli_open(cli->tree, fname, O_RDWR, DENY_NONE);
1047         if (fnum3 == -1) {
1048                 printf("open3 of %s failed (%s)\n", fname, cli_errstr(cli->tree));
1049                 return False;
1050         }
1051
1052         cli->session->pid = 1;
1053
1054         if (!cli_lock(cli->tree, fnum1, 0, 4, 0, WRITE_LOCK)) {
1055                 printf("lock1 failed (%s)\n", cli_errstr(cli->tree));
1056                 return False;
1057         }
1058
1059         if (cli_lock(cli->tree, fnum1, 0, 4, 0, WRITE_LOCK)) {
1060                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1061                 correct = False;
1062         } else {
1063                 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, 
1064                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
1065         }
1066
1067         if (cli_lock(cli->tree, fnum2, 0, 4, 0, WRITE_LOCK)) {
1068                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1069                 correct = False;
1070         } else {
1071                 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, 
1072                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
1073         }
1074
1075         if (cli_lock(cli->tree, fnum2, 0, 4, 0, READ_LOCK)) {
1076                 printf("READ lock2 succeeded! This is a locking bug\n");
1077                 correct = False;
1078         } else {
1079                 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, 
1080                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
1081         }
1082
1083         if (!cli_lock(cli->tree, fnum1, 100, 4, 0, WRITE_LOCK)) {
1084                 printf("lock at 100 failed (%s)\n", cli_errstr(cli->tree));
1085         }
1086
1087         cli->session->pid = 2;
1088
1089         if (cli_unlock(cli->tree, fnum1, 100, 4)) {
1090                 printf("unlock at 100 succeeded! This is a locking bug\n");
1091                 correct = False;
1092         }
1093
1094         if (cli_unlock(cli->tree, fnum1, 0, 4)) {
1095                 printf("unlock1 succeeded! This is a locking bug\n");
1096                 correct = False;
1097         } else {
1098                 if (!check_error(__LINE__, cli, 
1099                                  ERRDOS, ERRlock, 
1100                                  NT_STATUS_RANGE_NOT_LOCKED)) return False;
1101         }
1102
1103         if (cli_unlock(cli->tree, fnum1, 0, 8)) {
1104                 printf("unlock2 succeeded! This is a locking bug\n");
1105                 correct = False;
1106         } else {
1107                 if (!check_error(__LINE__, cli, 
1108                                  ERRDOS, ERRlock, 
1109                                  NT_STATUS_RANGE_NOT_LOCKED)) return False;
1110         }
1111
1112         if (cli_lock(cli->tree, fnum3, 0, 4, 0, WRITE_LOCK)) {
1113                 printf("lock3 succeeded! This is a locking bug\n");
1114                 correct = False;
1115         } else {
1116                 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
1117         }
1118
1119         cli->session->pid = 1;
1120
1121         if (!cli_close(cli->tree, fnum1)) {
1122                 printf("close1 failed (%s)\n", cli_errstr(cli->tree));
1123                 return False;
1124         }
1125
1126         if (!cli_close(cli->tree, fnum2)) {
1127                 printf("close2 failed (%s)\n", cli_errstr(cli->tree));
1128                 return False;
1129         }
1130
1131         if (!cli_close(cli->tree, fnum3)) {
1132                 printf("close3 failed (%s)\n", cli_errstr(cli->tree));
1133                 return False;
1134         }
1135
1136         if (!torture_close_connection(cli)) {
1137                 correct = False;
1138         }
1139
1140         printf("locktest2 finished\n");
1141
1142         return correct;
1143 }
1144
1145
1146 /*
1147   This test checks that 
1148
1149   1) the server supports the full offset range in lock requests
1150 */
1151 static BOOL run_locktest3(int dummy)
1152 {
1153         struct cli_state *cli1, *cli2;
1154         const char *fname = "\\lockt3.lck";
1155         int fnum1, fnum2, i;
1156         uint32 offset;
1157         BOOL correct = True;
1158
1159 #define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
1160
1161         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
1162                 return False;
1163         }
1164
1165         printf("starting locktest3\n");
1166
1167         printf("Testing 32 bit offset ranges\n");
1168
1169         cli_unlink(cli1->tree, fname);
1170
1171         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1172         if (fnum1 == -1) {
1173                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
1174                 return False;
1175         }
1176         fnum2 = cli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
1177         if (fnum2 == -1) {
1178                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
1179                 return False;
1180         }
1181
1182         printf("Establishing %d locks\n", torture_numops);
1183
1184         for (offset=i=0;i<torture_numops;i++) {
1185                 NEXT_OFFSET;
1186                 if (!cli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
1187                         printf("lock1 %d failed (%s)\n", 
1188                                i,
1189                                cli_errstr(cli1->tree));
1190                         return False;
1191                 }
1192
1193                 if (!cli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
1194                         printf("lock2 %d failed (%s)\n", 
1195                                i,
1196                                cli_errstr(cli1->tree));
1197                         return False;
1198                 }
1199         }
1200
1201         printf("Testing %d locks\n", torture_numops);
1202
1203         for (offset=i=0;i<torture_numops;i++) {
1204                 NEXT_OFFSET;
1205
1206                 if (cli_lock(cli1->tree, fnum1, offset-2, 1, 0, WRITE_LOCK)) {
1207                         printf("error: lock1 %d succeeded!\n", i);
1208                         return False;
1209                 }
1210
1211                 if (cli_lock(cli2->tree, fnum2, offset-1, 1, 0, WRITE_LOCK)) {
1212                         printf("error: lock2 %d succeeded!\n", i);
1213                         return False;
1214                 }
1215
1216                 if (cli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
1217                         printf("error: lock3 %d succeeded!\n", i);
1218                         return False;
1219                 }
1220
1221                 if (cli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
1222                         printf("error: lock4 %d succeeded!\n", i);
1223                         return False;
1224                 }
1225         }
1226
1227         printf("Removing %d locks\n", torture_numops);
1228
1229         for (offset=i=0;i<torture_numops;i++) {
1230                 NEXT_OFFSET;
1231
1232                 if (!cli_unlock(cli1->tree, fnum1, offset-1, 1)) {
1233                         printf("unlock1 %d failed (%s)\n", 
1234                                i,
1235                                cli_errstr(cli1->tree));
1236                         return False;
1237                 }
1238
1239                 if (!cli_unlock(cli2->tree, fnum2, offset-2, 1)) {
1240                         printf("unlock2 %d failed (%s)\n", 
1241                                i,
1242                                cli_errstr(cli1->tree));
1243                         return False;
1244                 }
1245         }
1246
1247         if (!cli_close(cli1->tree, fnum1)) {
1248                 printf("close1 failed (%s)\n", cli_errstr(cli1->tree));
1249                 return False;
1250         }
1251
1252         if (!cli_close(cli2->tree, fnum2)) {
1253                 printf("close2 failed (%s)\n", cli_errstr(cli2->tree));
1254                 return False;
1255         }
1256
1257         if (!cli_unlink(cli1->tree, fname)) {
1258                 printf("unlink failed (%s)\n", cli_errstr(cli1->tree));
1259                 return False;
1260         }
1261
1262         if (!torture_close_connection(cli1)) {
1263                 correct = False;
1264         }
1265         
1266         if (!torture_close_connection(cli2)) {
1267                 correct = False;
1268         }
1269
1270         printf("finished locktest3\n");
1271
1272         return correct;
1273 }
1274
1275 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1276         printf("** "); correct = False; \
1277         }
1278
1279 /*
1280   looks at overlapping locks
1281 */
1282 static BOOL run_locktest4(int dummy)
1283 {
1284         struct cli_state *cli1, *cli2;
1285         const char *fname = "\\lockt4.lck";
1286         int fnum1, fnum2, f;
1287         BOOL ret;
1288         char buf[1000];
1289         BOOL correct = True;
1290
1291         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
1292                 return False;
1293         }
1294
1295         printf("starting locktest4\n");
1296
1297         cli_unlink(cli1->tree, fname);
1298
1299         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1300         fnum2 = cli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
1301
1302         memset(buf, 0, sizeof(buf));
1303
1304         if (cli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1305                 printf("Failed to create file\n");
1306                 correct = False;
1307                 goto fail;
1308         }
1309
1310         ret = cli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK) &&
1311               cli_lock(cli1->tree, fnum1, 2, 4, 0, WRITE_LOCK);
1312         EXPECTED(ret, False);
1313         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1314             
1315         ret = cli_lock(cli1->tree, fnum1, 10, 4, 0, READ_LOCK) &&
1316               cli_lock(cli1->tree, fnum1, 12, 4, 0, READ_LOCK);
1317         EXPECTED(ret, True);
1318         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1319
1320         ret = cli_lock(cli1->tree, fnum1, 20, 4, 0, WRITE_LOCK) &&
1321               cli_lock(cli2->tree, fnum2, 22, 4, 0, WRITE_LOCK);
1322         EXPECTED(ret, False);
1323         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1324             
1325         ret = cli_lock(cli1->tree, fnum1, 30, 4, 0, READ_LOCK) &&
1326               cli_lock(cli2->tree, fnum2, 32, 4, 0, READ_LOCK);
1327         EXPECTED(ret, True);
1328         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1329         
1330         ret = (cli1->session->pid = 1, cli_lock(cli1->tree, fnum1, 40, 4, 0, WRITE_LOCK)) &&
1331               (cli1->session->pid = 2, cli_lock(cli1->tree, fnum1, 42, 4, 0, WRITE_LOCK));
1332         EXPECTED(ret, False);
1333         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1334             
1335         ret = (cli1->session->pid = 1, cli_lock(cli1->tree, fnum1, 50, 4, 0, READ_LOCK)) &&
1336               (cli1->session->pid = 2, cli_lock(cli1->tree, fnum1, 52, 4, 0, READ_LOCK));
1337         EXPECTED(ret, True);
1338         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1339
1340         ret = cli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK) &&
1341               cli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK);
1342         EXPECTED(ret, True);
1343         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1344
1345         ret = cli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK) &&
1346               cli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK);
1347         EXPECTED(ret, False);
1348         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1349
1350         ret = cli_lock(cli1->tree, fnum1, 80, 4, 0, READ_LOCK) &&
1351               cli_lock(cli1->tree, fnum1, 80, 4, 0, WRITE_LOCK);
1352         EXPECTED(ret, False);
1353         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1354
1355         ret = cli_lock(cli1->tree, fnum1, 90, 4, 0, WRITE_LOCK) &&
1356               cli_lock(cli1->tree, fnum1, 90, 4, 0, READ_LOCK);
1357         EXPECTED(ret, True);
1358         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1359
1360         ret = (cli1->session->pid = 1, cli_lock(cli1->tree, fnum1, 100, 4, 0, WRITE_LOCK)) &&
1361               (cli1->session->pid = 2, cli_lock(cli1->tree, fnum1, 100, 4, 0, READ_LOCK));
1362         EXPECTED(ret, False);
1363         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1364
1365         ret = cli_lock(cli1->tree, fnum1, 110, 4, 0, READ_LOCK) &&
1366               cli_lock(cli1->tree, fnum1, 112, 4, 0, READ_LOCK) &&
1367               cli_unlock(cli1->tree, fnum1, 110, 6);
1368         EXPECTED(ret, False);
1369         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
1370
1371
1372         ret = cli_lock(cli1->tree, fnum1, 120, 4, 0, WRITE_LOCK) &&
1373               (cli_read(cli2->tree, fnum2, buf, 120, 4) == 4);
1374         EXPECTED(ret, False);
1375         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
1376
1377         ret = cli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK) &&
1378               (cli_write(cli2->tree, fnum2, 0, buf, 130, 4) == 4);
1379         EXPECTED(ret, False);
1380         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
1381
1382
1383         ret = cli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK) &&
1384               cli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK) &&
1385               cli_unlock(cli1->tree, fnum1, 140, 4) &&
1386               cli_unlock(cli1->tree, fnum1, 140, 4);
1387         EXPECTED(ret, True);
1388         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
1389
1390
1391         ret = cli_lock(cli1->tree, fnum1, 150, 4, 0, WRITE_LOCK) &&
1392               cli_lock(cli1->tree, fnum1, 150, 4, 0, READ_LOCK) &&
1393               cli_unlock(cli1->tree, fnum1, 150, 4) &&
1394               (cli_read(cli2->tree, fnum2, buf, 150, 4) == 4) &&
1395               !(cli_write(cli2->tree, fnum2, 0, buf, 150, 4) == 4) &&
1396               cli_unlock(cli1->tree, fnum1, 150, 4);
1397         EXPECTED(ret, True);
1398         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
1399
1400         ret = cli_lock(cli1->tree, fnum1, 160, 4, 0, READ_LOCK) &&
1401               cli_unlock(cli1->tree, fnum1, 160, 4) &&
1402               (cli_write(cli2->tree, fnum2, 0, buf, 160, 4) == 4) &&            
1403               (cli_read(cli2->tree, fnum2, buf, 160, 4) == 4);          
1404         EXPECTED(ret, True);
1405         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
1406
1407         ret = cli_lock(cli1->tree, fnum1, 170, 4, 0, WRITE_LOCK) &&
1408               cli_unlock(cli1->tree, fnum1, 170, 4) &&
1409               (cli_write(cli2->tree, fnum2, 0, buf, 170, 4) == 4) &&            
1410               (cli_read(cli2->tree, fnum2, buf, 170, 4) == 4);          
1411         EXPECTED(ret, True);
1412         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
1413
1414         ret = cli_lock(cli1->tree, fnum1, 190, 4, 0, WRITE_LOCK) &&
1415               cli_lock(cli1->tree, fnum1, 190, 4, 0, READ_LOCK) &&
1416               cli_unlock(cli1->tree, fnum1, 190, 4) &&
1417               !(cli_write(cli2->tree, fnum2, 0, buf, 190, 4) == 4) &&           
1418               (cli_read(cli2->tree, fnum2, buf, 190, 4) == 4);          
1419         EXPECTED(ret, True);
1420         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
1421
1422         cli_close(cli1->tree, fnum1);
1423         cli_close(cli2->tree, fnum2);
1424         fnum1 = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1425         f = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1426         ret = cli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK) &&
1427               cli_lock(cli1->tree, f, 0, 1, 0, READ_LOCK) &&
1428               cli_close(cli1->tree, fnum1) &&
1429               ((fnum1 = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE)) != -1) &&
1430               cli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK);
1431         cli_close(cli1->tree, f);
1432         cli_close(cli1->tree, fnum1);
1433         EXPECTED(ret, True);
1434         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
1435
1436  fail:
1437         cli_close(cli1->tree, fnum1);
1438         cli_close(cli2->tree, fnum2);
1439         cli_unlink(cli1->tree, fname);
1440         torture_close_connection(cli1);
1441         torture_close_connection(cli2);
1442
1443         printf("finished locktest4\n");
1444         return correct;
1445 }
1446
1447 /*
1448   looks at lock upgrade/downgrade.
1449 */
1450 static BOOL run_locktest5(int dummy)
1451 {
1452         struct cli_state *cli1, *cli2;
1453         const char *fname = "\\lockt5.lck";
1454         int fnum1, fnum2, fnum3;
1455         BOOL ret;
1456         char buf[1000];
1457         BOOL correct = True;
1458
1459         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
1460                 return False;
1461         }
1462
1463         printf("starting locktest5\n");
1464
1465         cli_unlink(cli1->tree, fname);
1466
1467         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1468         fnum2 = cli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
1469         fnum3 = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1470
1471         memset(buf, 0, sizeof(buf));
1472
1473         if (cli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1474                 printf("Failed to create file\n");
1475                 correct = False;
1476                 goto fail;
1477         }
1478
1479         /* Check for NT bug... */
1480         ret = cli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK) &&
1481                   cli_lock(cli1->tree, fnum3, 0, 1, 0, READ_LOCK);
1482         cli_close(cli1->tree, fnum1);
1483         fnum1 = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1484         ret = cli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK);
1485         EXPECTED(ret, True);
1486         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
1487         cli_close(cli1->tree, fnum1);
1488         fnum1 = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1489         cli_unlock(cli1->tree, fnum3, 0, 1);
1490
1491         ret = cli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK) &&
1492               cli_lock(cli1->tree, fnum1, 1, 1, 0, READ_LOCK);
1493         EXPECTED(ret, True);
1494         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
1495
1496         ret = cli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK);
1497         EXPECTED(ret, False);
1498
1499         printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
1500
1501         /* Unlock the process 2 lock. */
1502         cli_unlock(cli2->tree, fnum2, 0, 4);
1503
1504         ret = cli_lock(cli1->tree, fnum3, 0, 4, 0, READ_LOCK);
1505         EXPECTED(ret, False);
1506
1507         printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
1508
1509         /* Unlock the process 1 fnum3 lock. */
1510         cli_unlock(cli1->tree, fnum3, 0, 4);
1511
1512         /* Stack 2 more locks here. */
1513         ret = cli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK) &&
1514                   cli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK);
1515
1516         EXPECTED(ret, True);
1517         printf("the same process %s stack read locks\n", ret?"can":"cannot");
1518
1519         /* Unlock the first process lock, then check this was the WRITE lock that was
1520                 removed. */
1521
1522         ret = cli_unlock(cli1->tree, fnum1, 0, 4) &&
1523                         cli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK);
1524
1525         EXPECTED(ret, True);
1526         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
1527
1528         /* Unlock the process 2 lock. */
1529         cli_unlock(cli2->tree, fnum2, 0, 4);
1530
1531         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
1532
1533         ret = cli_unlock(cli1->tree, fnum1, 1, 1) &&
1534                   cli_unlock(cli1->tree, fnum1, 0, 4) &&
1535                   cli_unlock(cli1->tree, fnum1, 0, 4);
1536
1537         EXPECTED(ret, True);
1538         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
1539
1540         /* Ensure the next unlock fails. */
1541         ret = cli_unlock(cli1->tree, fnum1, 0, 4);
1542         EXPECTED(ret, False);
1543         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
1544
1545         /* Ensure connection 2 can get a write lock. */
1546         ret = cli_lock(cli2->tree, fnum2, 0, 4, 0, WRITE_LOCK);
1547         EXPECTED(ret, True);
1548
1549         printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
1550
1551
1552  fail:
1553         cli_close(cli1->tree, fnum1);
1554         cli_close(cli2->tree, fnum2);
1555         cli_unlink(cli1->tree, fname);
1556         if (!torture_close_connection(cli1)) {
1557                 correct = False;
1558         }
1559         if (!torture_close_connection(cli2)) {
1560                 correct = False;
1561         }
1562
1563         printf("finished locktest5\n");
1564        
1565         return correct;
1566 }
1567
1568 /*
1569   tries the unusual lockingX locktype bits
1570 */
1571 static BOOL run_locktest6(int dummy)
1572 {
1573         struct cli_state *cli;
1574         const char *fname[1] = { "\\lock6.txt" };
1575         int i;
1576         int fnum;
1577         NTSTATUS status;
1578
1579         if (!torture_open_connection(&cli)) {
1580                 return False;
1581         }
1582
1583         printf("starting locktest6\n");
1584
1585         for (i=0;i<1;i++) {
1586                 printf("Testing %s\n", fname[i]);
1587
1588                 cli_unlink(cli->tree, fname[i]);
1589
1590                 fnum = cli_open(cli->tree, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1591                 status = cli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
1592                 cli_close(cli->tree, fnum);
1593                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
1594
1595                 fnum = cli_open(cli->tree, fname[i], O_RDWR, DENY_NONE);
1596                 status = cli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
1597                 cli_close(cli->tree, fnum);
1598                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
1599
1600                 cli_unlink(cli->tree, fname[i]);
1601         }
1602
1603         torture_close_connection(cli);
1604
1605         printf("finished locktest6\n");
1606         return True;
1607 }
1608
1609 static BOOL run_locktest7(int dummy)
1610 {
1611         struct cli_state *cli1;
1612         const char *fname = "\\lockt7.lck";
1613         int fnum1;
1614         char buf[200];
1615         BOOL correct = False;
1616
1617         if (!torture_open_connection(&cli1)) {
1618                 return False;
1619         }
1620
1621         printf("starting locktest7\n");
1622
1623         cli_unlink(cli1->tree, fname);
1624
1625         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1626
1627         memset(buf, 0, sizeof(buf));
1628
1629         if (cli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1630                 printf("Failed to create file\n");
1631                 goto fail;
1632         }
1633
1634         cli1->session->pid = 1;
1635
1636         if (!cli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK)) {
1637                 printf("Unable to apply read lock on range 130:4, error was %s\n", cli_errstr(cli1->tree));
1638                 goto fail;
1639         } else {
1640                 printf("pid1 successfully locked range 130:4 for READ\n");
1641         }
1642
1643         if (cli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
1644                 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1645                 goto fail;
1646         } else {
1647                 printf("pid1 successfully read the range 130:4\n");
1648         }
1649
1650         if (cli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
1651                 printf("pid1 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1652                 if (NT_STATUS_V(cli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
1653                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
1654                         goto fail;
1655                 }
1656         } else {
1657                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
1658                 goto fail;
1659         }
1660
1661         cli1->session->pid = 2;
1662
1663         if (cli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
1664                 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1665         } else {
1666                 printf("pid2 successfully read the range 130:4\n");
1667         }
1668
1669         if (cli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
1670                 printf("pid2 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1671                 if (NT_STATUS_V(cli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
1672                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
1673                         goto fail;
1674                 }
1675         } else {
1676                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
1677                 goto fail;
1678         }
1679
1680         cli1->session->pid = 1;
1681         cli_unlock(cli1->tree, fnum1, 130, 4);
1682
1683         if (!cli_lock(cli1->tree, fnum1, 130, 4, 0, WRITE_LOCK)) {
1684                 printf("Unable to apply write lock on range 130:4, error was %s\n", cli_errstr(cli1->tree));
1685                 goto fail;
1686         } else {
1687                 printf("pid1 successfully locked range 130:4 for WRITE\n");
1688         }
1689
1690         if (cli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
1691                 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1692                 goto fail;
1693         } else {
1694                 printf("pid1 successfully read the range 130:4\n");
1695         }
1696
1697         if (cli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
1698                 printf("pid1 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1699                 goto fail;
1700         } else {
1701                 printf("pid1 successfully wrote to the range 130:4\n");
1702         }
1703
1704         cli1->session->pid = 2;
1705
1706         if (cli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
1707                 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1708                 if (NT_STATUS_V(cli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
1709                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
1710                         goto fail;
1711                 }
1712         } else {
1713                 printf("pid2 successfully read the range 130:4 (should be denied)\n");
1714                 goto fail;
1715         }
1716
1717         if (cli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
1718                 printf("pid2 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1->tree));
1719                 if (NT_STATUS_V(cli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
1720                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
1721                         goto fail;
1722                 }
1723         } else {
1724                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
1725                 goto fail;
1726         }
1727
1728         cli_unlock(cli1->tree, fnum1, 130, 0);
1729         correct = True;
1730
1731 fail:
1732         cli_close(cli1->tree, fnum1);
1733         cli_unlink(cli1->tree, fname);
1734         torture_close_connection(cli1);
1735
1736         printf("finished locktest7\n");
1737         return correct;
1738 }
1739
1740 /*
1741 test whether fnums and tids open on one VC are available on another (a major
1742 security hole)
1743 */
1744 static BOOL run_fdpasstest(int dummy)
1745 {
1746         struct cli_state *cli1, *cli2;
1747         const char *fname = "\\fdpass.tst";
1748         int fnum1, oldtid;
1749         pstring buf;
1750
1751         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
1752                 return False;
1753         }
1754
1755         printf("starting fdpasstest\n");
1756
1757         cli_unlink(cli1->tree, fname);
1758
1759         printf("Opening a file on connection 1\n");
1760
1761         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1762         if (fnum1 == -1) {
1763                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
1764                 return False;
1765         }
1766
1767         printf("writing to file on connection 1\n");
1768
1769         if (cli_write(cli1->tree, fnum1, 0, "hello world\n", 0, 13) != 13) {
1770                 printf("write failed (%s)\n", cli_errstr(cli1->tree));
1771                 return False;
1772         }
1773
1774         oldtid = cli2->tree->tid;
1775         cli2->session->vuid = cli1->session->vuid;
1776         cli2->tree->tid = cli1->tree->tid;
1777         cli2->session->pid = cli1->session->pid;
1778
1779         printf("reading from file on connection 2\n");
1780
1781         if (cli_read(cli2->tree, fnum1, buf, 0, 13) == 13) {
1782                 printf("read succeeded! nasty security hole [%s]\n",
1783                        buf);
1784                 return False;
1785         }
1786
1787         cli_close(cli1->tree, fnum1);
1788         cli_unlink(cli1->tree, fname);
1789
1790         cli2->tree->tid = oldtid;
1791
1792         torture_close_connection(cli1);
1793         torture_close_connection(cli2);
1794
1795         printf("finished fdpasstest\n");
1796         return True;
1797 }
1798
1799
1800 /*
1801   This test checks that 
1802
1803   1) the server does not allow an unlink on a file that is open
1804 */
1805 static BOOL run_unlinktest(int dummy)
1806 {
1807         struct cli_state *cli;
1808         const char *fname = "\\unlink.tst";
1809         int fnum;
1810         BOOL correct = True;
1811
1812         if (!torture_open_connection(&cli)) {
1813                 return False;
1814         }
1815
1816         printf("starting unlink test\n");
1817
1818         cli_unlink(cli->tree, fname);
1819
1820         cli->session->pid = 1;
1821
1822         printf("Opening a file\n");
1823
1824         fnum = cli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1825         if (fnum == -1) {
1826                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli->tree));
1827                 return False;
1828         }
1829
1830         printf("Unlinking a open file\n");
1831
1832         if (cli_unlink(cli->tree, fname)) {
1833                 printf("error: server allowed unlink on an open file\n");
1834                 correct = False;
1835         } else {
1836                 correct = check_error(__LINE__, cli, ERRDOS, ERRbadshare, 
1837                                       NT_STATUS_SHARING_VIOLATION);
1838         }
1839
1840         cli_close(cli->tree, fnum);
1841         cli_unlink(cli->tree, fname);
1842
1843         if (!torture_close_connection(cli)) {
1844                 correct = False;
1845         }
1846
1847         printf("unlink test finished\n");
1848         
1849         return correct;
1850 }
1851
1852
1853 /*
1854 test how many open files this server supports on the one socket
1855 */
1856 static BOOL run_maxfidtest(int dummy)
1857 {
1858         struct cli_state *cli;
1859         const char *template = "\\maxfid.%d.%d";
1860         char *fname;
1861         int fnums[0x11000], i;
1862         int retries=4;
1863         BOOL correct = True;
1864
1865         cli = current_cli;
1866
1867         if (retries <= 0) {
1868                 printf("failed to connect\n");
1869                 return False;
1870         }
1871
1872         printf("Testing maximum number of open files\n");
1873
1874         for (i=0; i<0x11000; i++) {
1875                 asprintf(&fname, template, i,(int)getpid());
1876                 if ((fnums[i] = cli_open(cli->tree, fname, 
1877                                         O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) ==
1878                     -1) {
1879                         printf("open of %s failed (%s)\n", 
1880                                fname, cli_errstr(cli->tree));
1881                         printf("maximum fnum is %d\n", i);
1882                         break;
1883                 }
1884                 free(fname);
1885                 printf("%6d\r", i);
1886         }
1887         printf("%6d\n", i);
1888         i--;
1889
1890         printf("cleaning up\n");
1891         for (;i>=0;i--) {
1892                 asprintf(&fname, template, i,(int)getpid());
1893                 if (!cli_close(cli->tree, fnums[i])) {
1894                         printf("Close of fnum %d failed - %s\n", fnums[i], cli_errstr(cli->tree));
1895                 }
1896                 if (!cli_unlink(cli->tree, fname)) {
1897                         printf("unlink of %s failed (%s)\n", 
1898                                fname, cli_errstr(cli->tree));
1899                         correct = False;
1900                 }
1901                 free(fname);
1902                 printf("%6d\r", i);
1903         }
1904         printf("%6d\n", 0);
1905
1906         printf("maxfid test finished\n");
1907         if (!torture_close_connection(cli)) {
1908                 correct = False;
1909         }
1910         return correct;
1911 }
1912
1913 /* send smb negprot commands, not reading the response */
1914 static BOOL run_negprot_nowait(int dummy)
1915 {
1916         int i;
1917         struct cli_state *cli;
1918         BOOL correct = True;
1919
1920         printf("starting negprot nowait test\n");
1921
1922         cli = open_nbt_connection();
1923         if (!cli) {
1924                 return False;
1925         }
1926
1927         printf("Establishing protocol negotiations - connect with another client\n");
1928
1929         for (i=0;i<50000;i++) {
1930                 smb_negprot_send(cli->transport, PROTOCOL_NT1);
1931         }
1932
1933         if (!torture_close_connection(cli)) {
1934                 correct = False;
1935         }
1936
1937         printf("finished negprot nowait test\n");
1938
1939         return correct;
1940 }
1941
1942
1943 /*
1944   This checks how the getatr calls works
1945 */
1946 static BOOL run_attrtest(int dummy)
1947 {
1948         struct cli_state *cli;
1949         int fnum;
1950         time_t t, t2;
1951         const char *fname = "\\attrib123456789.tst";
1952         BOOL correct = True;
1953
1954         printf("starting attrib test\n");
1955
1956         if (!torture_open_connection(&cli)) {
1957                 return False;
1958         }
1959
1960         cli_unlink(cli->tree, fname);
1961         fnum = cli_open(cli->tree, fname, 
1962                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1963         cli_close(cli->tree, fnum);
1964
1965         if (!cli_getatr(cli->tree, fname, NULL, NULL, &t)) {
1966                 printf("getatr failed (%s)\n", cli_errstr(cli->tree));
1967                 correct = False;
1968         }
1969
1970         printf("New file time is %s", ctime(&t));
1971
1972         if (abs(t - time(NULL)) > 60*60*24*10) {
1973                 printf("ERROR: SMBgetatr bug. time is %s",
1974                        ctime(&t));
1975                 t = time(NULL);
1976                 correct = False;
1977         }
1978
1979         t2 = t-60*60*24; /* 1 day ago */
1980
1981         printf("Setting file time to %s", ctime(&t2));
1982
1983         if (!cli_setatr(cli->tree, fname, 0, t2)) {
1984                 printf("setatr failed (%s)\n", cli_errstr(cli->tree));
1985                 correct = True;
1986         }
1987
1988         if (!cli_getatr(cli->tree, fname, NULL, NULL, &t)) {
1989                 printf("getatr failed (%s)\n", cli_errstr(cli->tree));
1990                 correct = True;
1991         }
1992
1993         printf("Retrieved file time as %s", ctime(&t));
1994
1995         if (t != t2) {
1996                 printf("ERROR: getatr/setatr bug. times are\n%s",
1997                        ctime(&t));
1998                 printf("%s", ctime(&t2));
1999                 correct = True;
2000         }
2001
2002         cli_unlink(cli->tree, fname);
2003
2004         if (!torture_close_connection(cli)) {
2005                 correct = False;
2006         }
2007
2008         printf("attrib test finished\n");
2009
2010         return correct;
2011 }
2012
2013
2014 /*
2015   This checks a couple of trans2 calls
2016 */
2017 static BOOL run_trans2test(int dummy)
2018 {
2019         struct cli_state *cli;
2020         int fnum;
2021         size_t size;
2022         time_t c_time, a_time, m_time, w_time, m_time2;
2023         const char *fname = "\\trans2.tst";
2024         const char *dname = "\\trans2";
2025         const char *fname2 = "\\trans2\\trans2.tst";
2026         const char *pname;
2027         BOOL correct = True;
2028
2029         printf("starting trans2 test\n");
2030
2031         if (!torture_open_connection(&cli)) {
2032                 return False;
2033         }
2034
2035         cli_unlink(cli->tree, fname);
2036
2037         printf("Testing qfileinfo\n");
2038         
2039         fnum = cli_open(cli->tree, fname, 
2040                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2041         if (!cli_qfileinfo(cli->tree, fnum, NULL, &size, &c_time, &a_time, &m_time,
2042                            NULL, NULL)) {
2043                 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(cli->tree));
2044                 correct = False;
2045         }
2046
2047         printf("Testing NAME_INFO\n");
2048
2049         if (!cli_qfilename(cli->tree, fnum, &pname)) {
2050                 printf("ERROR: qfilename failed (%s)\n", cli_errstr(cli->tree));
2051                 correct = False;
2052         }
2053
2054         if (!pname || strcmp(pname, fname)) {
2055                 printf("qfilename gave different name? [%s] [%s]\n",
2056                        fname, pname);
2057                 correct = False;
2058         }
2059
2060         cli_close(cli->tree, fnum);
2061         cli_unlink(cli->tree, fname);
2062
2063         fnum = cli_open(cli->tree, fname, 
2064                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2065         if (fnum == -1) {
2066                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli->tree));
2067                 return False;
2068         }
2069         cli_close(cli->tree, fnum);
2070
2071         printf("Checking for sticky create times\n");
2072
2073         if (!cli_qpathinfo(cli->tree, fname, &c_time, &a_time, &m_time, &size, NULL)) {
2074                 printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(cli->tree));
2075                 correct = False;
2076         } else {
2077                 if (c_time != m_time) {
2078                         printf("create time=%s", ctime(&c_time));
2079                         printf("modify time=%s", ctime(&m_time));
2080                         printf("This system appears to have sticky create times\n");
2081                 }
2082                 if (a_time % (60*60) == 0) {
2083                         printf("access time=%s", ctime(&a_time));
2084                         printf("This system appears to set a midnight access time\n");
2085                         correct = False;
2086                 }
2087
2088                 if (abs(m_time - time(NULL)) > 60*60*24*7) {
2089                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
2090                         correct = False;
2091                 }
2092         }
2093
2094
2095         cli_unlink(cli->tree, fname);
2096         fnum = cli_open(cli->tree, fname, 
2097                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2098         cli_close(cli->tree, fnum);
2099         if (!cli_qpathinfo2(cli->tree, fname, &c_time, &a_time, &m_time, 
2100                             &w_time, &size, NULL, NULL)) {
2101                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(cli->tree));
2102                 correct = False;
2103         } else {
2104                 if (w_time < 60*60*24*2) {
2105                         printf("write time=%s", ctime(&w_time));
2106                         printf("This system appears to set a initial 0 write time\n");
2107                         correct = False;
2108                 }
2109         }
2110
2111         cli_unlink(cli->tree, fname);
2112
2113
2114         /* check if the server updates the directory modification time
2115            when creating a new file */
2116         if (!cli_mkdir(cli->tree, dname)) {
2117                 printf("ERROR: mkdir failed (%s)\n", cli_errstr(cli->tree));
2118                 correct = False;
2119         }
2120         sleep(3);
2121         if (!cli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time, 
2122                             &w_time, &size, NULL, NULL)) {
2123                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(cli->tree));
2124                 correct = False;
2125         }
2126
2127         fnum = cli_open(cli->tree, fname2, 
2128                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2129         cli_write(cli->tree, fnum,  0, (char *)&fnum, 0, sizeof(fnum));
2130         cli_close(cli->tree, fnum);
2131         if (!cli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time2, 
2132                             &w_time, &size, NULL, NULL)) {
2133                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(cli->tree));
2134                 correct = False;
2135         } else {
2136                 if (m_time2 == m_time) {
2137                         printf("This system does not update directory modification times\n");
2138                         correct = False;
2139                 }
2140         }
2141         cli_unlink(cli->tree, fname2);
2142         cli_rmdir(cli->tree, dname);
2143
2144         if (!torture_close_connection(cli)) {
2145                 correct = False;
2146         }
2147
2148         printf("trans2 test finished\n");
2149
2150         return correct;
2151 }
2152
2153 /*
2154   Test delete on close semantics.
2155  */
2156 static BOOL run_deletetest(int dummy)
2157 {
2158         struct cli_state *cli1;
2159         struct cli_state *cli2 = NULL;
2160         const char *fname = "\\delete.file";
2161         int fnum1 = -1;
2162         int fnum2 = -1;
2163         BOOL correct = True;
2164         
2165         printf("starting delete test\n");
2166         
2167         if (!torture_open_connection(&cli1)) {
2168                 return False;
2169         }
2170         
2171         /* Test 1 - this should delete the file on close. */
2172         
2173         cli_setatr(cli1->tree, fname, 0, 0);
2174         cli_unlink(cli1->tree, fname);
2175         
2176         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
2177                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 
2178                                    NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2179         
2180         if (fnum1 == -1) {
2181                 printf("[1] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2182                 correct = False;
2183                 goto fail;
2184         }
2185         
2186         if (!cli_close(cli1->tree, fnum1)) {
2187                 printf("[1] close failed (%s)\n", cli_errstr(cli1->tree));
2188                 correct = False;
2189                 goto fail;
2190         }
2191
2192         fnum1 = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
2193         if (fnum1 != -1) {
2194                 printf("[1] open of %s succeeded (should fail)\n", fname);
2195                 correct = False;
2196                 goto fail;
2197         }
2198         
2199         printf("first delete on close test succeeded.\n");
2200         
2201         /* Test 2 - this should delete the file on close. */
2202         
2203         cli_setatr(cli1->tree, fname, 0, 0);
2204         cli_unlink(cli1->tree, fname);
2205         
2206         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS,
2207                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, 
2208                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2209         
2210         if (fnum1 == -1) {
2211                 printf("[2] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2212                 correct = False;
2213                 goto fail;
2214         }
2215         
2216         if (!cli_nt_delete_on_close(cli1->tree, fnum1, True)) {
2217                 printf("[2] setting delete_on_close failed (%s)\n", cli_errstr(cli1->tree));
2218                 correct = False;
2219                 goto fail;
2220         }
2221         
2222         if (!cli_close(cli1->tree, fnum1)) {
2223                 printf("[2] close failed (%s)\n", cli_errstr(cli1->tree));
2224                 correct = False;
2225                 goto fail;
2226         }
2227         
2228         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2229         if (fnum1 != -1) {
2230                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
2231                 if (!cli_close(cli1->tree, fnum1)) {
2232                         printf("[2] close failed (%s)\n", cli_errstr(cli1->tree));
2233                         correct = False;
2234                         goto fail;
2235                 }
2236                 cli_unlink(cli1->tree, fname);
2237         } else
2238                 printf("second delete on close test succeeded.\n");
2239         
2240         /* Test 3 - ... */
2241         cli_setatr(cli1->tree, fname, 0, 0);
2242         cli_unlink(cli1->tree, fname);
2243
2244         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
2245                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2246
2247         if (fnum1 == -1) {
2248                 printf("[3] open - 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2249                 correct = False;
2250                 goto fail;
2251         }
2252
2253         /* This should fail with a sharing violation - open for delete is only compatible
2254            with SHARE_DELETE. */
2255
2256         fnum2 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
2257                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
2258                                    NTCREATEX_DISP_OPEN, 0, 0);
2259
2260         if (fnum2 != -1) {
2261                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
2262                 correct = False;
2263                 goto fail;
2264         }
2265
2266         /* This should succeed. */
2267
2268         fnum2 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
2269                         NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN, 0, 0);
2270
2271         if (fnum2 == -1) {
2272                 printf("[3] open  - 2 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2273                 correct = False;
2274                 goto fail;
2275         }
2276
2277         if (!cli_nt_delete_on_close(cli1->tree, fnum1, True)) {
2278                 printf("[3] setting delete_on_close failed (%s)\n", cli_errstr(cli1->tree));
2279                 correct = False;
2280                 goto fail;
2281         }
2282         
2283         if (!cli_close(cli1->tree, fnum1)) {
2284                 printf("[3] close 1 failed (%s)\n", cli_errstr(cli1->tree));
2285                 correct = False;
2286                 goto fail;
2287         }
2288         
2289         if (!cli_close(cli1->tree, fnum2)) {
2290                 printf("[3] close 2 failed (%s)\n", cli_errstr(cli1->tree));
2291                 correct = False;
2292                 goto fail;
2293         }
2294         
2295         /* This should fail - file should no longer be there. */
2296
2297         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2298         if (fnum1 != -1) {
2299                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
2300                 if (!cli_close(cli1->tree, fnum1)) {
2301                         printf("[3] close failed (%s)\n", cli_errstr(cli1->tree));
2302                 }
2303                 cli_unlink(cli1->tree, fname);
2304                 correct = False;
2305                 goto fail;
2306         } else
2307                 printf("third delete on close test succeeded.\n");
2308
2309         /* Test 4 ... */
2310         cli_setatr(cli1->tree, fname, 0, 0);
2311         cli_unlink(cli1->tree, fname);
2312
2313         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, 
2314                                    SA_RIGHT_FILE_READ_DATA  | 
2315                                    SA_RIGHT_FILE_WRITE_DATA |
2316                                    STD_RIGHT_DELETE_ACCESS,
2317                                    FILE_ATTRIBUTE_NORMAL, 
2318                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
2319                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2320                                                                 
2321         if (fnum1 == -1) {
2322                 printf("[4] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2323                 correct = False;
2324                 goto fail;
2325         }
2326
2327         /* This should succeed. */
2328         fnum2 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ,
2329                                    FILE_ATTRIBUTE_NORMAL, 
2330                                    NTCREATEX_SHARE_ACCESS_READ  | 
2331                                    NTCREATEX_SHARE_ACCESS_WRITE |
2332                                    NTCREATEX_SHARE_ACCESS_DELETE, 
2333                                    NTCREATEX_DISP_OPEN, 0, 0);
2334         if (fnum2 == -1) {
2335                 printf("[4] open  - 2 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2336                 correct = False;
2337                 goto fail;
2338         }
2339         
2340         if (!cli_close(cli1->tree, fnum2)) {
2341                 printf("[4] close - 1 failed (%s)\n", cli_errstr(cli1->tree));
2342                 correct = False;
2343                 goto fail;
2344         }
2345         
2346         if (!cli_nt_delete_on_close(cli1->tree, fnum1, True)) {
2347                 printf("[4] setting delete_on_close failed (%s)\n", cli_errstr(cli1->tree));
2348                 correct = False;
2349                 goto fail;
2350         }
2351         
2352         /* This should fail - no more opens once delete on close set. */
2353         fnum2 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ,
2354                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
2355                                    NTCREATEX_DISP_OPEN, 0, 0);
2356         if (fnum2 != -1) {
2357                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
2358                 correct = False;
2359                 goto fail;
2360         } else
2361                 printf("fourth delete on close test succeeded.\n");
2362         
2363         if (!cli_close(cli1->tree, fnum1)) {
2364                 printf("[4] close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2365                 correct = False;
2366                 goto fail;
2367         }
2368         
2369         /* Test 5 ... */
2370         cli_setatr(cli1->tree, fname, 0, 0);
2371         cli_unlink(cli1->tree, fname);
2372         
2373         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2374         if (fnum1 == -1) {
2375                 printf("[5] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2376                 correct = False;
2377                 goto fail;
2378         }
2379
2380         /* This should fail - only allowed on NT opens with DELETE access. */
2381
2382         if (cli_nt_delete_on_close(cli1->tree, fnum1, True)) {
2383                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
2384                 correct = False;
2385                 goto fail;
2386         }
2387
2388         if (!cli_close(cli1->tree, fnum1)) {
2389                 printf("[5] close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2390                 correct = False;
2391                 goto fail;
2392         }
2393         
2394         printf("fifth delete on close test succeeded.\n");
2395         
2396         /* Test 6 ... */
2397         cli_setatr(cli1->tree, fname, 0, 0);
2398         cli_unlink(cli1->tree, fname);
2399         
2400         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, 
2401                                    SA_RIGHT_FILE_READ_DATA | SA_RIGHT_FILE_WRITE_DATA,
2402                                    FILE_ATTRIBUTE_NORMAL, 
2403                                    NTCREATEX_SHARE_ACCESS_READ  |
2404                                    NTCREATEX_SHARE_ACCESS_WRITE |
2405                                    NTCREATEX_SHARE_ACCESS_DELETE,
2406                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2407         
2408         if (fnum1 == -1) {
2409                 printf("[6] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2410                 correct = False;
2411                 goto fail;
2412         }
2413         
2414         /* This should fail - only allowed on NT opens with DELETE access. */
2415         
2416         if (cli_nt_delete_on_close(cli1->tree, fnum1, True)) {
2417                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
2418                 correct = False;
2419                 goto fail;
2420         }
2421
2422         if (!cli_close(cli1->tree, fnum1)) {
2423                 printf("[6] close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2424                 correct = False;
2425                 goto fail;
2426         }
2427
2428         printf("sixth delete on close test succeeded.\n");
2429         
2430         /* Test 7 ... */
2431         cli_setatr(cli1->tree, fname, 0, 0);
2432         cli_unlink(cli1->tree, fname);
2433         
2434         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, 
2435                                    SA_RIGHT_FILE_READ_DATA  | 
2436                                    SA_RIGHT_FILE_WRITE_DATA |
2437                                    STD_RIGHT_DELETE_ACCESS,
2438                                    FILE_ATTRIBUTE_NORMAL, 0, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2439                                                                 
2440         if (fnum1 == -1) {
2441                 printf("[7] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2442                 correct = False;
2443                 goto fail;
2444         }
2445
2446         if (!cli_nt_delete_on_close(cli1->tree, fnum1, True)) {
2447                 printf("[7] setting delete_on_close on file failed !\n");
2448                 correct = False;
2449                 goto fail;
2450         }
2451         
2452         if (!cli_nt_delete_on_close(cli1->tree, fnum1, False)) {
2453                 printf("[7] unsetting delete_on_close on file failed !\n");
2454                 correct = False;
2455                 goto fail;
2456         }
2457
2458         if (!cli_close(cli1->tree, fnum1)) {
2459                 printf("[7] close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2460                 correct = False;
2461                 goto fail;
2462         }
2463         
2464         /* This next open should succeed - we reset the flag. */
2465         
2466         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2467         if (fnum1 == -1) {
2468                 printf("[5] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2469                 correct = False;
2470                 goto fail;
2471         }
2472
2473         if (!cli_close(cli1->tree, fnum1)) {
2474                 printf("[7] close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2475                 correct = False;
2476                 goto fail;
2477         }
2478
2479         printf("seventh delete on close test succeeded.\n");
2480         
2481         /* Test 7 ... */
2482         cli_setatr(cli1->tree, fname, 0, 0);
2483         cli_unlink(cli1->tree, fname);
2484         
2485         if (!torture_open_connection(&cli2)) {
2486                 printf("[8] failed to open second connection.\n");
2487                 correct = False;
2488                 goto fail;
2489         }
2490
2491         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|STD_RIGHT_DELETE_ACCESS,
2492                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
2493                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2494         
2495         if (fnum1 == -1) {
2496                 printf("[8] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2497                 correct = False;
2498                 goto fail;
2499         }
2500
2501         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|STD_RIGHT_DELETE_ACCESS,
2502                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
2503                                    NTCREATEX_DISP_OPEN, 0, 0);
2504         
2505         if (fnum2 == -1) {
2506                 printf("[8] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2507                 correct = False;
2508                 goto fail;
2509         }
2510
2511         if (!cli_nt_delete_on_close(cli1->tree, fnum1, True)) {
2512                 printf("[8] setting delete_on_close on file failed !\n");
2513                 correct = False;
2514                 goto fail;
2515         }
2516         
2517         if (!cli_close(cli1->tree, fnum1)) {
2518                 printf("[8] close - 1 failed (%s)\n", cli_errstr(cli1->tree));
2519                 correct = False;
2520                 goto fail;
2521         }
2522
2523         if (!cli_close(cli2->tree, fnum2)) {
2524                 printf("[8] close - 2 failed (%s)\n", cli_errstr(cli2->tree));
2525                 correct = False;
2526                 goto fail;
2527         }
2528
2529         /* This should fail.. */
2530         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2531         if (fnum1 != -1) {
2532                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
2533                 goto fail;
2534                 correct = False;
2535         } else
2536                 printf("eighth delete on close test succeeded.\n");
2537
2538         /* This should fail - we need to set DELETE_ACCESS. */
2539         fnum1 = cli_nt_create_full(cli1->tree, fname, 0,SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA,
2540                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2541         
2542         if (fnum1 != -1) {
2543                 printf("[9] open of %s succeeded should have failed!\n", fname);
2544                 correct = False;
2545                 goto fail;
2546         }
2547
2548         printf("ninth delete on close test succeeded.\n");
2549
2550         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|STD_RIGHT_DELETE_ACCESS,
2551                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2552         if (fnum1 == -1) {
2553                 printf("[10] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2554                 correct = False;
2555                 goto fail;
2556         }
2557
2558         /* This should delete the file. */
2559         if (!cli_close(cli1->tree, fnum1)) {
2560                 printf("[10] close failed (%s)\n", cli_errstr(cli1->tree));
2561                 correct = False;
2562                 goto fail;
2563         }
2564
2565         /* This should fail.. */
2566         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2567         if (fnum1 != -1) {
2568                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
2569                 goto fail;
2570                 correct = False;
2571         } else
2572                 printf("tenth delete on close test succeeded.\n");
2573         printf("finished delete test\n");
2574
2575   fail:
2576         /* FIXME: This will crash if we aborted before cli2 got
2577          * intialized, because these functions don't handle
2578          * uninitialized connections. */
2579                 
2580         cli_close(cli1->tree, fnum1);
2581         cli_close(cli1->tree, fnum2);
2582         cli_setatr(cli1->tree, fname, 0, 0);
2583         cli_unlink(cli1->tree, fname);
2584
2585         if (!torture_close_connection(cli1)) {
2586                 correct = False;
2587         }
2588         if (!torture_close_connection(cli2)) {
2589                 correct = False;
2590         }
2591         return correct;
2592 }
2593
2594
2595 /*
2596   print out server properties
2597  */
2598 static BOOL run_properties(int dummy)
2599 {
2600         struct cli_state *cli;
2601         BOOL correct = True;
2602         
2603         printf("starting properties test\n");
2604         
2605         ZERO_STRUCT(cli);
2606
2607         if (!torture_open_connection(&cli)) {
2608                 return False;
2609         }
2610         
2611         d_printf("Capabilities 0x%08x\n", cli->transport->negotiate.capabilities);
2612
2613         if (!torture_close_connection(cli)) {
2614                 correct = False;
2615         }
2616
2617         return correct;
2618 }
2619
2620
2621
2622 /* FIRST_DESIRED_ACCESS   0xf019f */
2623 #define FIRST_DESIRED_ACCESS   SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|SA_RIGHT_FILE_APPEND_DATA|\
2624                                SA_RIGHT_FILE_READ_EA|                           /* 0xf */ \
2625                                SA_RIGHT_FILE_WRITE_EA|SA_RIGHT_FILE_READ_ATTRIBUTES|     /* 0x90 */ \
2626                                SA_RIGHT_FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
2627                                STD_RIGHT_DELETE_ACCESS|STD_RIGHT_READ_CONTROL_ACCESS|\
2628                                STD_RIGHT_WRITE_DAC_ACCESS|STD_RIGHT_WRITE_OWNER_ACCESS     /* 0xf0000 */
2629 /* SECOND_DESIRED_ACCESS  0xe0080 */
2630 #define SECOND_DESIRED_ACCESS  SA_RIGHT_FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
2631                                STD_RIGHT_READ_CONTROL_ACCESS|STD_RIGHT_WRITE_DAC_ACCESS|\
2632                                STD_RIGHT_WRITE_OWNER_ACCESS                      /* 0xe0000 */
2633
2634 #if 0
2635 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
2636                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
2637                                SA_RIGHT_FILE_READ_DATA|\
2638                                WRITE_OWNER_ACCESS                      /* */
2639 #endif
2640
2641 /*
2642   Test ntcreate calls made by xcopy
2643  */
2644 static BOOL run_xcopy(int dummy)
2645 {
2646         struct cli_state *cli1;
2647         const char *fname = "\\test.txt";
2648         BOOL correct = True;
2649         int fnum1, fnum2;
2650
2651         printf("starting xcopy test\n");
2652         
2653         if (!torture_open_connection(&cli1)) {
2654                 return False;
2655         }
2656         
2657         fnum1 = cli_nt_create_full(cli1->tree, fname, 0,
2658                                    FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
2659                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 
2660                                    0x4044, 0);
2661
2662         if (fnum1 == -1) {
2663                 printf("First open failed - %s\n", cli_errstr(cli1->tree));
2664                 return False;
2665         }
2666
2667         fnum2 = cli_nt_create_full(cli1->tree, fname, 0,
2668                                    SECOND_DESIRED_ACCESS, 0,
2669                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN, 
2670                                    0x200000, 0);
2671         if (fnum2 == -1) {
2672                 printf("second open failed - %s\n", cli_errstr(cli1->tree));
2673                 return False;
2674         }
2675         
2676         if (!torture_close_connection(cli1)) {
2677                 correct = False;
2678         }
2679         
2680         return correct;
2681 }
2682
2683 /*
2684   Test rename on files open with share delete and no share delete.
2685  */
2686 static BOOL run_rename(int dummy)
2687 {
2688         struct cli_state *cli1;
2689         const char *fname = "\\test.txt";
2690         const char *fname1 = "\\test1.txt";
2691         BOOL correct = True;
2692         int fnum1;
2693
2694         printf("starting rename test\n");
2695         
2696         if (!torture_open_connection(&cli1)) {
2697                 return False;
2698         }
2699         
2700         cli_unlink(cli1->tree, fname);
2701         cli_unlink(cli1->tree, fname1);
2702         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
2703                                    NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2704
2705         if (fnum1 == -1) {
2706                 printf("First open failed - %s\n", cli_errstr(cli1->tree));
2707                 return False;
2708         }
2709
2710         if (!cli_rename(cli1->tree, fname, fname1)) {
2711                 printf("First rename failed (this is correct) - %s\n", cli_errstr(cli1->tree));
2712         } else {
2713                 printf("First rename succeeded - this should have failed !\n");
2714                 correct = False;
2715         }
2716
2717         if (!cli_close(cli1->tree, fnum1)) {
2718                 printf("close - 1 failed (%s)\n", cli_errstr(cli1->tree));
2719                 return False;
2720         }
2721
2722         cli_unlink(cli1->tree, fname);
2723         cli_unlink(cli1->tree, fname1);
2724         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
2725 #if 0
2726                                    NTCREATEX_SHARE_ACCESS_DELETE|NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2727 #else
2728                                    NTCREATEX_SHARE_ACCESS_DELETE|NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2729 #endif
2730
2731         if (fnum1 == -1) {
2732                 printf("Second open failed - %s\n", cli_errstr(cli1->tree));
2733                 return False;
2734         }
2735
2736         if (!cli_rename(cli1->tree, fname, fname1)) {
2737                 printf("Second rename failed - this should have succeeded - %s\n", cli_errstr(cli1->tree));
2738                 correct = False;
2739         } else {
2740                 printf("Second rename succeeded\n");
2741         }
2742
2743         if (!cli_close(cli1->tree, fnum1)) {
2744                 printf("close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2745                 return False;
2746         }
2747
2748         cli_unlink(cli1->tree, fname);
2749         cli_unlink(cli1->tree, fname1);
2750
2751         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_READ_CONTROL_ACCESS, FILE_ATTRIBUTE_NORMAL,
2752                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2753
2754         if (fnum1 == -1) {
2755                 printf("Third open failed - %s\n", cli_errstr(cli1->tree));
2756                 return False;
2757         }
2758
2759
2760 #if 0
2761   {
2762   int fnum2;
2763
2764         fnum2 = cli_nt_create_full(cli1->tree, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
2765                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2766
2767         if (fnum2 == -1) {
2768                 printf("Fourth open failed - %s\n", cli_errstr(cli1->tree));
2769                 return False;
2770         }
2771         if (!cli_nt_delete_on_close(cli1->tree, fnum2, True)) {
2772                 printf("[8] setting delete_on_close on file failed !\n");
2773                 return False;
2774         }
2775         
2776         if (!cli_close(cli1->tree, fnum2)) {
2777                 printf("close - 4 failed (%s)\n", cli_errstr(cli1->tree));
2778                 return False;
2779         }
2780   }
2781 #endif
2782
2783         if (!cli_rename(cli1->tree, fname, fname1)) {
2784                 printf("Third rename failed - this should have succeeded - %s\n", cli_errstr(cli1->tree));
2785                 correct = False;
2786         } else {
2787                 printf("Third rename succeeded\n");
2788         }
2789
2790         if (!cli_close(cli1->tree, fnum1)) {
2791                 printf("close - 3 failed (%s)\n", cli_errstr(cli1->tree));
2792                 return False;
2793         }
2794
2795         cli_unlink(cli1->tree, fname);
2796         cli_unlink(cli1->tree, fname1);
2797
2798         if (!torture_close_connection(cli1)) {
2799                 correct = False;
2800         }
2801         
2802         return correct;
2803 }
2804
2805 static BOOL run_pipe_number(int dummy)
2806 {
2807         struct cli_state *cli1;
2808         const char *pipe_name = "\\WKSSVC";
2809         int fnum;
2810         int num_pipes = 0;
2811
2812         printf("starting pipenumber test\n");
2813         if (!torture_open_connection(&cli1)) {
2814                 return False;
2815         }
2816
2817         while(1) {
2818                 fnum = cli_nt_create_full(cli1->tree, pipe_name, 0, SA_RIGHT_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
2819                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OPEN_IF, 0, 0);
2820
2821                 if (fnum == -1) {
2822                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, cli_errstr(cli1->tree));
2823                         break;
2824                 }
2825                 num_pipes++;
2826         }
2827
2828         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
2829         torture_close_connection(cli1);
2830         return True;
2831 }
2832
2833
2834 /*
2835   Test open mode returns on read-only files.
2836  */
2837  static BOOL run_opentest(int dummy)
2838 {
2839         static struct cli_state *cli1;
2840         static struct cli_state *cli2;
2841         const char *fname = "\\readonly.file";
2842         int fnum1, fnum2;
2843         char buf[20];
2844         size_t fsize;
2845         BOOL correct = True;
2846         char *tmp_path;
2847         int failures = 0;
2848
2849         printf("starting open test\n");
2850         
2851         if (!torture_open_connection(&cli1)) {
2852                 return False;
2853         }
2854         
2855         cli_setatr(cli1->tree, fname, 0, 0);
2856         cli_unlink(cli1->tree, fname);
2857         
2858         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
2859         if (fnum1 == -1) {
2860                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2861                 return False;
2862         }
2863
2864         if (!cli_close(cli1->tree, fnum1)) {
2865                 printf("close2 failed (%s)\n", cli_errstr(cli1->tree));
2866                 return False;
2867         }
2868         
2869         if (!cli_setatr(cli1->tree, fname, FILE_ATTRIBUTE_READONLY, 0)) {
2870                 printf("cli_setatr failed (%s)\n", cli_errstr(cli1->tree));
2871                 CHECK_MAX_FAILURES(error_test1);
2872                 return False;
2873         }
2874         
2875         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
2876         if (fnum1 == -1) {
2877                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2878                 CHECK_MAX_FAILURES(error_test1);
2879                 return False;
2880         }
2881         
2882         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
2883         fnum2 = cli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
2884         
2885         if (check_error(__LINE__, cli1, ERRDOS, ERRnoaccess, 
2886                         NT_STATUS_ACCESS_DENIED)) {
2887                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
2888         }
2889         
2890         printf("finished open test 1\n");
2891 error_test1:
2892         cli_close(cli1->tree, fnum1);
2893         
2894         /* Now try not readonly and ensure ERRbadshare is returned. */
2895         
2896         cli_setatr(cli1->tree, fname, 0, 0);
2897         
2898         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
2899         if (fnum1 == -1) {
2900                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2901                 return False;
2902         }
2903         
2904         /* This will fail - but the error should be ERRshare. */
2905         fnum2 = cli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
2906         
2907         if (check_error(__LINE__, cli1, ERRDOS, ERRbadshare, 
2908                         NT_STATUS_SHARING_VIOLATION)) {
2909                 printf("correct error code ERRDOS/ERRbadshare returned\n");
2910         }
2911         
2912         if (!cli_close(cli1->tree, fnum1)) {
2913                 printf("close2 failed (%s)\n", cli_errstr(cli1->tree));
2914                 return False;
2915         }
2916         
2917         cli_unlink(cli1->tree, fname);
2918         
2919         printf("finished open test 2\n");
2920         
2921         /* Test truncate open disposition on file opened for read. */
2922         
2923         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
2924         if (fnum1 == -1) {
2925                 printf("(3) open (1) of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2926                 return False;
2927         }
2928         
2929         /* write 20 bytes. */
2930         
2931         memset(buf, '\0', 20);
2932
2933         if (cli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
2934                 printf("write failed (%s)\n", cli_errstr(cli1->tree));
2935                 correct = False;
2936         }
2937
2938         if (!cli_close(cli1->tree, fnum1)) {
2939                 printf("(3) close1 failed (%s)\n", cli_errstr(cli1->tree));
2940                 return False;
2941         }
2942         
2943         /* Ensure size == 20. */
2944         if (!cli_getatr(cli1->tree, fname, NULL, &fsize, NULL)) {
2945                 printf("(3) getatr failed (%s)\n", cli_errstr(cli1->tree));
2946                 CHECK_MAX_FAILURES(error_test3);
2947                 return False;
2948         }
2949         
2950         if (fsize != 20) {
2951                 printf("(3) file size != 20\n");
2952                 CHECK_MAX_FAILURES(error_test3);
2953                 return False;
2954         }
2955
2956         /* Now test if we can truncate a file opened for readonly. */
2957         
2958         fnum1 = cli_open(cli1->tree, fname, O_RDONLY|O_TRUNC, DENY_NONE);
2959         if (fnum1 == -1) {
2960                 printf("(3) open (2) of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2961                 CHECK_MAX_FAILURES(error_test3);
2962                 return False;
2963         }
2964         
2965         if (!cli_close(cli1->tree, fnum1)) {
2966                 printf("close2 failed (%s)\n", cli_errstr(cli1->tree));
2967                 return False;
2968         }
2969
2970         /* Ensure size == 0. */
2971         if (!cli_getatr(cli1->tree, fname, NULL, &fsize, NULL)) {
2972                 printf("(3) getatr failed (%s)\n", cli_errstr(cli1->tree));
2973                 CHECK_MAX_FAILURES(error_test3);
2974                 return False;
2975         }
2976
2977         if (fsize != 0) {
2978                 printf("(3) file size != 0\n");
2979                 CHECK_MAX_FAILURES(error_test3);
2980                 return False;
2981         }
2982         printf("finished open test 3\n");
2983 error_test3:    
2984         cli_unlink(cli1->tree, fname);
2985
2986
2987         printf("testing ctemp\n");
2988         fnum1 = cli_ctemp(cli1->tree, "\\", &tmp_path);
2989         if (fnum1 == -1) {
2990                 printf("ctemp failed (%s)\n", cli_errstr(cli1->tree));
2991                 CHECK_MAX_FAILURES(error_test4);
2992                 return False;
2993         }
2994         printf("ctemp gave path %s\n", tmp_path);
2995         if (!cli_close(cli1->tree, fnum1)) {
2996                 printf("close of temp failed (%s)\n", cli_errstr(cli1->tree));
2997         }
2998         if (!cli_unlink(cli1->tree, tmp_path)) {
2999                 printf("unlink of temp failed (%s)\n", cli_errstr(cli1->tree));
3000         }
3001 error_test4:    
3002         /* Test the non-io opens... */
3003
3004         if (!torture_open_connection(&cli2)) {
3005                 return False;
3006         }
3007         
3008         cli_setatr(cli2->tree, fname, 0, 0);
3009         cli_unlink(cli2->tree, fname);
3010         
3011         printf("TEST #1 testing 2 non-io opens (no delete)\n");
3012         
3013         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3014                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3015
3016         if (fnum1 == -1) {
3017                 printf("test 1 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3018                 CHECK_MAX_FAILURES(error_test10);
3019                 return False;
3020         }
3021
3022         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3023                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3024         if (fnum2 == -1) {
3025                 printf("test 1 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3026                 CHECK_MAX_FAILURES(error_test10);
3027                 return False;
3028         }
3029
3030         if (!cli_close(cli1->tree, fnum1)) {
3031                 printf("test 1 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3032                 return False;
3033         }
3034         if (!cli_close(cli2->tree, fnum2)) {
3035                 printf("test 1 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3036                 return False;
3037         }
3038
3039         printf("non-io open test #1 passed.\n");
3040 error_test10:
3041         cli_unlink(cli1->tree, fname);
3042
3043         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
3044         
3045         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3046                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3047
3048         if (fnum1 == -1) {
3049                 printf("test 2 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3050                 CHECK_MAX_FAILURES(error_test20);
3051                 return False;
3052         }
3053
3054         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3055                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3056
3057         if (fnum2 == -1) {
3058                 printf("test 2 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3059                 CHECK_MAX_FAILURES(error_test20);
3060                 return False;
3061         }
3062
3063         if (!cli_close(cli1->tree, fnum1)) {
3064                 printf("test 1 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3065                 return False;
3066         }
3067         if (!cli_close(cli2->tree, fnum2)) {
3068                 printf("test 1 close 2 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3069                 return False;
3070         }
3071
3072         printf("non-io open test #2 passed.\n");
3073 error_test20:
3074         cli_unlink(cli1->tree, fname);
3075
3076         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
3077         
3078         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3079                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3080
3081         if (fnum1 == -1) {
3082                 printf("test 3 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3083                 CHECK_MAX_FAILURES(error_test30);
3084                 return False;
3085         }
3086
3087         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3088                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3089
3090         if (fnum2 == -1) {
3091                 printf("test 3 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3092                 CHECK_MAX_FAILURES(error_test30);
3093                 return False;
3094         }
3095
3096         if (!cli_close(cli1->tree, fnum1)) {
3097                 printf("test 3 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3098                 return False;
3099         }
3100         if (!cli_close(cli2->tree, fnum2)) {
3101                 printf("test 3 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3102                 return False;
3103         }
3104
3105         printf("non-io open test #3 passed.\n");
3106 error_test30:
3107         cli_unlink(cli1->tree, fname);
3108
3109         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
3110         
3111         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3112                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3113
3114         if (fnum1 == -1) {
3115                 printf("test 4 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3116                 CHECK_MAX_FAILURES(error_test40);
3117                 return False;
3118         }
3119
3120         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3121                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3122
3123         if (fnum2 != -1) {
3124                 printf("test 4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, cli_errstr(cli2->tree));
3125                 CHECK_MAX_FAILURES(error_test40);
3126                 return False;
3127         }
3128
3129         printf("test 4 open 2 of %s gave %s (correct error should be %s)\n", fname, cli_errstr(cli2->tree), "sharing violation");
3130
3131         if (!cli_close(cli1->tree, fnum1)) {
3132                 printf("test 4 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3133                 return False;
3134         }
3135
3136         printf("non-io open test #4 passed.\n");
3137 error_test40:
3138         cli_unlink(cli1->tree, fname);
3139
3140         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
3141         
3142         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3143                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3144
3145         if (fnum1 == -1) {
3146                 printf("test 5 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3147                 CHECK_MAX_FAILURES(error_test50);
3148                 return False;
3149         }
3150
3151         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3152                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3153
3154         if (fnum2 == -1) {
3155                 printf("test 5 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3156                 CHECK_MAX_FAILURES(error_test50);
3157                 return False;
3158         }
3159
3160         if (!cli_close(cli1->tree, fnum1)) {
3161                 printf("test 5 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3162                 return False;
3163         }
3164
3165         if (!cli_close(cli2->tree, fnum2)) {
3166                 printf("test 5 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3167                 return False;
3168         }
3169
3170         printf("non-io open test #5 passed.\n");
3171 error_test50:
3172         printf("TEST #6 testing 1 non-io open, one io open\n");
3173         
3174         cli_unlink(cli1->tree, fname);
3175
3176         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
3177                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3178
3179         if (fnum1 == -1) {
3180                 printf("test 6 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3181                 CHECK_MAX_FAILURES(error_test60);
3182                 return False;
3183         }
3184
3185         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3186                                    NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OPEN_IF, 0, 0);
3187
3188         if (fnum2 == -1) {
3189                 printf("test 6 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3190                 CHECK_MAX_FAILURES(error_test60);
3191                 return False;
3192         }
3193
3194         if (!cli_close(cli1->tree, fnum1)) {
3195                 printf("test 6 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3196                 return False;
3197         }
3198
3199         if (!cli_close(cli2->tree, fnum2)) {
3200                 printf("test 6 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3201                 return False;
3202         }
3203
3204         printf("non-io open test #6 passed.\n");
3205 error_test60:
3206         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
3207
3208         cli_unlink(cli1->tree, fname);
3209
3210         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
3211                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3212
3213         if (fnum1 == -1) {
3214                 printf("test 7 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3215                 CHECK_MAX_FAILURES(error_test70);
3216                 return False;
3217         }
3218
3219         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3220                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3221
3222         if (fnum2 != -1) {
3223                 printf("test 7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, cli_errstr(cli2->tree));
3224                 CHECK_MAX_FAILURES(error_test70);
3225                 return False;
3226         }
3227
3228         printf("test 7 open 2 of %s gave %s (correct error should be %s)\n", fname, cli_errstr(cli2->tree), "sharing violation");
3229
3230         if (!cli_close(cli1->tree, fnum1)) {
3231                 printf("test 7 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3232                 return False;
3233         }
3234
3235         printf("non-io open test #7 passed.\n");
3236 error_test70:
3237         cli_unlink(cli1->tree, fname);
3238
3239         if (!torture_close_connection(cli1)) {
3240                 correct = False;
3241         }
3242         if (!torture_close_connection(cli2)) {
3243                 correct = False;
3244         }
3245         
3246         return correct;
3247 }
3248
3249
3250 static uint32 open_attrs_table[] = {
3251                 FILE_ATTRIBUTE_NORMAL,
3252                 FILE_ATTRIBUTE_ARCHIVE,
3253                 FILE_ATTRIBUTE_READONLY,
3254                 FILE_ATTRIBUTE_HIDDEN,
3255                 FILE_ATTRIBUTE_SYSTEM,
3256
3257                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
3258                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
3259                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
3260                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
3261                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
3262                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
3263
3264                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
3265                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
3266                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
3267                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
3268 };
3269
3270 struct trunc_open_results {
3271         unsigned int num;
3272         uint32 init_attr;
3273         uint32 trunc_attr;
3274         uint32 result_attr;
3275 };
3276
3277 static struct trunc_open_results attr_results[] = {
3278         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
3279         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
3280         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
3281         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
3282         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
3283         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
3284         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3285         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3286         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
3287         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3288         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3289         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
3290         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3291         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3292         { 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 },
3293         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3294         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3295         { 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 },
3296         { 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 },
3297         { 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 },
3298         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3299         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3300         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
3301         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3302         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3303         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
3304 };
3305
3306 static BOOL run_openattrtest(int dummy)
3307 {
3308         struct cli_state *cli1;
3309         const char *fname = "\\openattr.file";
3310         int fnum1;
3311         BOOL correct = True;
3312         uint16 attr;
3313         unsigned int i, j, k, l;
3314         int failures = 0;
3315
3316         printf("starting open attr test\n");
3317         
3318         if (!torture_open_connection(&cli1)) {
3319                 return False;
3320         }
3321         
3322         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
3323                 cli_setatr(cli1->tree, fname, 0, 0);
3324                 cli_unlink(cli1->tree, fname);
3325                 fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_WRITE_DATA, open_attrs_table[i],
3326                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3327
3328                 if (fnum1 == -1) {
3329                         printf("open %d (1) of %s failed (%s)\n", i, fname, cli_errstr(cli1->tree));
3330                         return False;
3331                 }
3332
3333                 if (!cli_close(cli1->tree, fnum1)) {
3334                         printf("close %d (1) of %s failed (%s)\n", i, fname, cli_errstr(cli1->tree));
3335                         return False;
3336                 }
3337
3338                 for (j = 0; j < ARRAY_SIZE(open_attrs_table); j++) {
3339                         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, 
3340                                                    SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA, 
3341                                                    open_attrs_table[j],
3342                                                    NTCREATEX_SHARE_ACCESS_NONE, 
3343                                                    NTCREATEX_DISP_OVERWRITE, 0, 0);
3344
3345                         if (fnum1 == -1) {
3346                                 for (l = 0; l < ARRAY_SIZE(attr_results); l++) {
3347                                         if (attr_results[l].num == k) {
3348                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
3349                                                                 k, open_attrs_table[i],
3350                                                                 open_attrs_table[j],
3351                                                                 fname, NT_STATUS_V(cli_nt_error(cli1->tree)), cli_errstr(cli1->tree));
3352                                                 correct = False;
3353                                                 CHECK_MAX_FAILURES(error_exit);
3354                                         }
3355                                 }
3356                                 if (NT_STATUS_V(cli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) {
3357                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
3358                                                         k, open_attrs_table[i], open_attrs_table[j],
3359                                                         cli_errstr(cli1->tree));
3360                                         correct = False;
3361                                         CHECK_MAX_FAILURES(error_exit);
3362                                 }
3363 #if 0
3364                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
3365 #endif
3366                                 k++;
3367                                 continue;
3368                         }
3369
3370                         if (!cli_close(cli1->tree, fnum1)) {
3371                                 printf("close %d (2) of %s failed (%s)\n", j, fname, cli_errstr(cli1->tree));
3372                                 return False;
3373                         }
3374
3375                         if (!cli_getatr(cli1->tree, fname, &attr, NULL, NULL)) {
3376                                 printf("getatr(2) failed (%s)\n", cli_errstr(cli1->tree));
3377                                 return False;
3378                         }
3379
3380 #if 0
3381                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
3382                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
3383 #endif
3384
3385                         for (l = 0; l < ARRAY_SIZE(attr_results); l++) {
3386                                 if (attr_results[l].num == k) {
3387                                         if (attr != attr_results[l].result_attr ||
3388                                                         open_attrs_table[i] != attr_results[l].init_attr ||
3389                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
3390                                                 printf("[%d] getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
3391                                                         k, open_attrs_table[i],
3392                                                         open_attrs_table[j],
3393                                                         (unsigned int)attr,
3394                                                         attr_results[l].result_attr);
3395                                                 correct = False;
3396                                                 CHECK_MAX_FAILURES(error_exit);
3397                                         }
3398                                         break;
3399                                 }
3400                         }
3401                         k++;
3402                 }
3403         }
3404 error_exit:
3405         cli_setatr(cli1->tree, fname, 0, 0);
3406         cli_unlink(cli1->tree, fname);
3407
3408         printf("open attr test %s.\n", correct ? "passed" : "failed");
3409
3410         if (!torture_close_connection(cli1)) {
3411                 correct = False;
3412         }
3413         return correct;
3414 }
3415
3416 static void list_fn(file_info *finfo, const char *name, void *state)
3417 {
3418         
3419 }
3420
3421 /*
3422   test directory listing speed
3423  */
3424 static BOOL run_dirtest(int dummy)
3425 {
3426         int i;
3427         struct cli_state *cli;
3428         int fnum;
3429         double t1;
3430         BOOL correct = True;
3431
3432         printf("starting directory test\n");
3433
3434         if (!torture_open_connection(&cli)) {
3435                 return False;
3436         }
3437
3438         printf("Creating %d random filenames\n", torture_numops);
3439
3440         srandom(0);
3441         for (i=0;i<torture_numops;i++) {
3442                 char *fname;
3443                 asprintf(&fname, "\\%x", (int)random());
3444                 fnum = cli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
3445                 if (fnum == -1) {
3446                         fprintf(stderr,"Failed to open %s\n", fname);
3447                         return False;
3448                 }
3449                 cli_close(cli->tree, fnum);
3450                 free(fname);
3451         }
3452
3453         t1 = end_timer();
3454
3455         printf("Matched %d\n", cli_list(cli->tree, "a*.*", 0, list_fn, NULL));
3456         printf("Matched %d\n", cli_list(cli->tree, "b*.*", 0, list_fn, NULL));
3457         printf("Matched %d\n", cli_list(cli->tree, "xyzabc", 0, list_fn, NULL));
3458
3459         printf("dirtest core %g seconds\n", end_timer() - t1);
3460
3461         srandom(0);
3462         for (i=0;i<torture_numops;i++) {
3463                 char *fname;
3464                 asprintf(&fname, "\\%x", (int)random());
3465                 cli_unlink(cli->tree, fname);
3466                 free(fname);
3467         }
3468
3469         if (!torture_close_connection(cli)) {
3470                 correct = False;
3471         }
3472
3473         printf("finished dirtest\n");
3474
3475         return correct;
3476 }
3477
3478 static void del_fn(file_info *finfo, const char *mask, void *state)
3479 {
3480         struct cli_state *pcli = (struct cli_state *)state;
3481         char *fname;
3482         asprintf(&fname, "\\LISTDIR\\%s", finfo->name);
3483
3484         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
3485                 return;
3486
3487         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
3488                 if (!cli_rmdir(pcli->tree, fname))
3489                         printf("del_fn: failed to rmdir %s, error=%s\n", fname, cli_errstr(pcli->tree) );
3490         } else {
3491                 if (!cli_unlink(pcli->tree, fname))
3492                         printf("del_fn: failed to unlink %s, error=%s\n", fname, cli_errstr(pcli->tree) );
3493         }
3494         free(fname);
3495 }
3496
3497
3498 /*
3499   sees what IOCTLs are supported
3500  */
3501 BOOL torture_ioctl_test(int dummy)
3502 {
3503         struct cli_state *cli;
3504         uint16 device, function;
3505         int fnum;
3506         const char *fname = "\\ioctl.dat";
3507         NTSTATUS status;
3508         union smb_ioctl parms;
3509         TALLOC_CTX *mem_ctx;
3510
3511         if (!torture_open_connection(&cli)) {
3512                 return False;
3513         }
3514
3515         mem_ctx = talloc_init("ioctl_test");
3516
3517         printf("starting ioctl test\n");
3518
3519         cli_unlink(cli->tree, fname);
3520
3521         fnum = cli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
3522         if (fnum == -1) {
3523                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli->tree));
3524                 return False;
3525         }
3526
3527         parms.ioctl.level = RAW_IOCTL_IOCTL;
3528         parms.ioctl.in.request = IOCTL_QUERY_JOB_INFO;
3529         status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
3530         printf("ioctl job info: %s\n", cli_errstr(cli->tree));
3531
3532         for (device=0;device<0x100;device++) {
3533                 printf("testing device=0x%x\n", device);
3534                 for (function=0;function<0x100;function++) {
3535                         parms.ioctl.in.request = (device << 16) | function;
3536                         status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
3537
3538                         if (NT_STATUS_IS_OK(status)) {
3539                                 printf("ioctl device=0x%x function=0x%x OK : %d bytes\n", 
3540                                         device, function, parms.ioctl.out.blob.length);
3541                         }
3542                 }
3543         }
3544
3545         if (!torture_close_connection(cli)) {
3546                 return False;
3547         }
3548
3549         return True;
3550 }
3551
3552
3553 /*
3554   tries variants of chkpath
3555  */
3556 BOOL torture_chkpath_test(int dummy)
3557 {
3558         struct cli_state *cli;
3559         int fnum;
3560         BOOL ret;
3561
3562         if (!torture_open_connection(&cli)) {
3563                 return False;
3564         }
3565
3566         printf("starting chkpath test\n");
3567
3568         printf("Testing valid and invalid paths\n");
3569
3570         /* cleanup from an old run */
3571         cli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
3572         cli_unlink(cli->tree, "\\chkpath.dir\\*");
3573         cli_rmdir(cli->tree, "\\chkpath.dir");
3574
3575         if (!cli_mkdir(cli->tree, "\\chkpath.dir")) {
3576                 printf("mkdir1 failed : %s\n", cli_errstr(cli->tree));
3577                 return False;
3578         }
3579
3580         if (!cli_mkdir(cli->tree, "\\chkpath.dir\\dir2")) {
3581                 printf("mkdir2 failed : %s\n", cli_errstr(cli->tree));
3582                 return False;
3583         }
3584
3585         fnum = cli_open(cli->tree, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
3586         if (fnum == -1) {
3587                 printf("open1 failed (%s)\n", cli_errstr(cli->tree));
3588                 return False;
3589         }
3590         cli_close(cli->tree, fnum);
3591
3592         if (!cli_chkpath(cli->tree, "\\chkpath.dir")) {
3593                 printf("chkpath1 failed: %s\n", cli_errstr(cli->tree));
3594                 ret = False;
3595         }
3596
3597         if (!cli_chkpath(cli->tree, "\\chkpath.dir\\dir2")) {
3598                 printf("chkpath2 failed: %s\n", cli_errstr(cli->tree));
3599                 ret = False;
3600         }
3601
3602         if (!cli_chkpath(cli->tree, "\\chkpath.dir\\foo.txt")) {
3603                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath, 
3604                                   NT_STATUS_NOT_A_DIRECTORY);
3605         } else {
3606                 printf("* chkpath on a file should fail\n");
3607                 ret = False;
3608         }
3609
3610         if (!cli_chkpath(cli->tree, "\\chkpath.dir\\bar.txt")) {
3611                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadfile, 
3612                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
3613         } else {
3614                 printf("* chkpath on a non existent file should fail\n");
3615                 ret = False;
3616         }
3617
3618         if (!cli_chkpath(cli->tree, "\\chkpath.dir\\dirxx\\bar.txt")) {
3619                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath, 
3620                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
3621         } else {
3622                 printf("* chkpath on a non existent component should fail\n");
3623                 ret = False;
3624         }
3625
3626         cli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
3627         cli_unlink(cli->tree, "\\chkpath.dir\\*");
3628         cli_rmdir(cli->tree, "\\chkpath.dir");
3629
3630         if (!torture_close_connection(cli)) {
3631                 return False;
3632         }
3633
3634         return ret;
3635 }
3636
3637 static BOOL run_dirtest1(int dummy)
3638 {
3639         int i;
3640         struct cli_state *cli;
3641         int fnum, num_seen;
3642         BOOL correct = True;
3643
3644         printf("starting directory test\n");
3645
3646         if (!torture_open_connection(&cli)) {
3647                 return False;
3648         }
3649
3650         cli_list(cli->tree, "\\LISTDIR\\*", 0, del_fn, cli);
3651         cli_list(cli->tree, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
3652         if (cli_deltree(cli->tree, "\\LISTDIR") == -1) {
3653                 fprintf(stderr,"Failed to deltree %s, error=%s\n", "\\LISTDIR", cli_errstr(cli->tree));
3654                 return False;
3655         }
3656         if (!cli_mkdir(cli->tree, "\\LISTDIR")) {
3657                 fprintf(stderr,"Failed to mkdir %s, error=%s\n", "\\LISTDIR", cli_errstr(cli->tree));
3658                 return False;
3659         }
3660
3661         printf("Creating %d files\n", torture_entries);
3662
3663         /* Create torture_entries files and torture_entries directories. */
3664         for (i=0;i<torture_entries;i++) {
3665                 char *fname;
3666                 asprintf(&fname, "\\LISTDIR\\f%d", i);
3667                 fnum = cli_nt_create_full(cli->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
3668                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3669                 if (fnum == -1) {
3670                         fprintf(stderr,"Failed to open %s, error=%s\n", fname, cli_errstr(cli->tree));
3671                         return False;
3672                 }
3673                 free(fname);
3674                 cli_close(cli->tree, fnum);
3675         }
3676         for (i=0;i<torture_entries;i++) {
3677                 char *fname;
3678                 asprintf(&fname, "\\LISTDIR\\d%d", i);
3679                 if (!cli_mkdir(cli->tree, fname)) {
3680                         fprintf(stderr,"Failed to open %s, error=%s\n", fname, cli_errstr(cli->tree));
3681                         return False;
3682                 }
3683                 free(fname);
3684         }
3685
3686         /* Now ensure that doing an old list sees both files and directories. */
3687         num_seen = cli_list_old(cli->tree, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, NULL);
3688         printf("num_seen = %d\n", num_seen );
3689         /* We should see (torture_entries) each of files & directories + . and .. */
3690         if (num_seen != (2*torture_entries)+2) {
3691                 correct = False;
3692                 fprintf(stderr,"entry count mismatch, should be %d, was %d\n",
3693                         (2*torture_entries)+2, num_seen);
3694         }
3695                 
3696
3697         /* Ensure if we have the "must have" bits we only see the
3698          * relevant entries.
3699          */
3700         num_seen = cli_list_old(cli->tree, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, NULL);
3701         printf("num_seen = %d\n", num_seen );
3702         if (num_seen != torture_entries+2) {
3703                 correct = False;
3704                 fprintf(stderr,"entry count mismatch, should be %d, was %d\n",
3705                         torture_entries+2, num_seen);
3706         }
3707
3708         num_seen = cli_list_old(cli->tree, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, NULL);
3709         printf("num_seen = %d\n", num_seen );
3710         if (num_seen != torture_entries) {
3711                 correct = False;
3712                 fprintf(stderr,"entry count mismatch, should be %d, was %d\n",
3713                         torture_entries, num_seen);
3714         }
3715
3716         /* Delete everything. */
3717         cli_list(cli->tree, "\\LISTDIR\\*", 0, del_fn, cli);
3718         cli_list(cli->tree, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
3719         cli_rmdir(cli->tree, "\\LISTDIR");
3720
3721 #if 0
3722         printf("Matched %d\n", cli_list(cli->tree, "a*.*", 0, list_fn, NULL));
3723         printf("Matched %d\n", cli_list(cli->tree, "b*.*", 0, list_fn, NULL));
3724         printf("Matched %d\n", cli_list(cli->tree, "xyzabc", 0, list_fn, NULL));
3725 #endif
3726
3727         if (!torture_close_connection(cli)) {
3728                 correct = False;
3729         }
3730
3731         printf("finished dirtest1\n");
3732
3733         return correct;
3734 }
3735
3736
3737 /*
3738    simple test harness for playing with deny modes
3739  */
3740 static BOOL run_deny3test(int dummy)
3741 {
3742         struct cli_state *cli1, *cli2;
3743         int fnum1, fnum2;
3744         const char *fname;
3745
3746         printf("starting deny3 test\n");
3747
3748         printf("Testing simple deny modes\n");
3749         
3750         if (!torture_open_connection(&cli1)) {
3751                 return False;
3752         }
3753         if (!torture_open_connection(&cli2)) {
3754                 return False;
3755         }
3756
3757         fname = "\\deny_dos1.dat";
3758
3759         cli_unlink(cli1->tree, fname);
3760         fnum1 = cli_open(cli1->tree, fname, O_CREAT|O_TRUNC|O_WRONLY, DENY_DOS);
3761         fnum2 = cli_open(cli1->tree, fname, O_CREAT|O_TRUNC|O_WRONLY, DENY_DOS);
3762         if (fnum1 != -1) cli_close(cli1->tree, fnum1);
3763         if (fnum2 != -1) cli_close(cli1->tree, fnum2);
3764         cli_unlink(cli1->tree, fname);
3765         printf("fnum1=%d fnum2=%d\n", fnum1, fnum2);
3766
3767
3768         fname = "\\deny_dos2.dat";
3769
3770         cli_unlink(cli1->tree, fname);
3771         fnum1 = cli_open(cli1->tree, fname, O_CREAT|O_TRUNC|O_WRONLY, DENY_DOS);
3772         fnum2 = cli_open(cli2->tree, fname, O_CREAT|O_TRUNC|O_WRONLY, DENY_DOS);
3773         if (fnum1 != -1) cli_close(cli1->tree, fnum1);
3774         if (fnum2 != -1) cli_close(cli2->tree, fnum2);
3775         cli_unlink(cli1->tree, fname);
3776         printf("fnum1=%d fnum2=%d\n", fnum1, fnum2);
3777
3778
3779         torture_close_connection(cli1);
3780         torture_close_connection(cli2);
3781
3782         return True;
3783 }
3784
3785 static void sigcont(void)
3786 {
3787 }
3788
3789 static double create_procs(BOOL (*fn)(int), BOOL *result)
3790 {
3791         int i, status;
3792         volatile pid_t *child_status;
3793         volatile BOOL *child_status_out;
3794         int synccount;
3795         int tries = 8;
3796         double start_time_limit = 10 + (nprocs * 1.5);
3797
3798         synccount = 0;
3799
3800         signal(SIGCONT, sigcont);
3801
3802         child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*nprocs);
3803         if (!child_status) {
3804                 printf("Failed to setup shared memory\n");
3805                 return -1;
3806         }
3807
3808         child_status_out = (volatile BOOL *)shm_setup(sizeof(BOOL)*nprocs);
3809         if (!child_status_out) {
3810                 printf("Failed to setup result status shared memory\n");
3811                 return -1;
3812         }
3813
3814         for (i = 0; i < nprocs; i++) {
3815                 child_status[i] = 0;
3816                 child_status_out[i] = True;
3817         }
3818
3819         start_timer();
3820
3821         for (i=0;i<nprocs;i++) {
3822                 procnum = i;
3823                 if (fork() == 0) {
3824                         char *myname;
3825                         pid_t mypid = getpid();
3826                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
3827
3828                         asprintf(&myname, "CLIENT%d", i);
3829                         lp_set_cmdline("netbios name", myname);
3830                         free(myname);
3831
3832                         while (1) {
3833                                 if (torture_open_connection(&current_cli)) break;
3834                                 if (tries-- == 0) {
3835                                         printf("pid %d failed to start\n", (int)getpid());
3836                                         _exit(1);
3837                                 }
3838                                 msleep(100);    
3839                         }
3840
3841                         child_status[i] = getpid();
3842
3843                         pause();
3844
3845                         if (child_status[i]) {
3846                                 printf("Child %d failed to start!\n", i);
3847                                 child_status_out[i] = 1;
3848                                 _exit(1);
3849                         }
3850
3851                         child_status_out[i] = fn(i);
3852                         _exit(0);
3853                 }
3854         }
3855
3856         do {
3857                 synccount = 0;
3858                 for (i=0;i<nprocs;i++) {
3859                         if (child_status[i]) synccount++;
3860                 }
3861                 if (synccount == nprocs) break;
3862                 msleep(100);
3863         } while (end_timer() < start_time_limit);
3864
3865         if (synccount != nprocs) {
3866                 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
3867                 *result = False;
3868                 return end_timer();
3869         }
3870
3871         printf("Starting %d clients\n", nprocs);
3872
3873         /* start the client load */
3874         start_timer();
3875         for (i=0;i<nprocs;i++) {
3876                 child_status[i] = 0;
3877         }
3878         kill(0, SIGCONT);
3879
3880         printf("%d clients started\n", nprocs);
3881
3882         for (i=0;i<nprocs;i++) {
3883                 int ret;
3884                 while ((ret=waitpid(0, &status, 0)) == -1 && errno == EINTR) /* noop */ ;
3885                 if (ret == -1 || WEXITSTATUS(status) != 0) {
3886                         *result = False;
3887                 }
3888         }
3889
3890         printf("\n");
3891         
3892         for (i=0;i<nprocs;i++) {
3893                 if (!child_status_out[i]) {
3894                         *result = False;
3895                 }
3896         }
3897         return end_timer();
3898 }
3899
3900 #define FLAG_MULTIPROC 1
3901
3902 static struct {
3903         const char *name;
3904         BOOL (*fn)(int);
3905         unsigned flags;
3906 } torture_ops[] = {
3907         {"FDPASS", run_fdpasstest, 0},
3908         {"LOCK1",  run_locktest1,  0},
3909         {"LOCK2",  run_locktest2,  0},
3910         {"LOCK3",  run_locktest3,  0},
3911         {"LOCK4",  run_locktest4,  0},
3912         {"LOCK5",  run_locktest5,  0},
3913         {"LOCK6",  run_locktest6,  0},
3914         {"LOCK7",  run_locktest7,  0},
3915         {"UNLINK", run_unlinktest, 0},
3916         {"ATTR",   run_attrtest,&nbs