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