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