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