r863: Added test to ensure an open and locked file can be truncated by a second open.
[bbaumbach/samba-autobuild/.git] / source4 / torture / torture.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-2003
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 int torture_nprocs=4;
24 int torture_numops=100;
25 int torture_entries=1000;
26 int torture_failures=1;
27 static int procnum; /* records process count number when forking */
28 static struct cli_state *current_cli;
29 static BOOL use_oplocks;
30 static BOOL use_level_II_oplocks;
31 static BOOL use_kerberos;
32
33 BOOL torture_showall = False;
34
35 #define CHECK_MAX_FAILURES(label) do { if (++failures >= torture_failures) goto label; } while (0)
36
37 static struct cli_state *open_nbt_connection(void)
38 {
39         struct nmb_name called, calling;
40         struct in_addr ip;
41         struct cli_state *cli;
42         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 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 eclass, uint32 ecode, NTSTATUS nterr)
174 {
175         if (cli_is_dos_error(c->tree)) {
176                 uint8 class;
177                 uint32 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 offset, uint32 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                 unsigned n = (unsigned)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         unsigned int i = 0;
325         char buf[131072];
326         char buf_rd[131072];
327         unsigned count;
328         unsigned 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))
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 = ((unsigned)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         uchar buf[131072];
428         uchar 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 = ((unsigned)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         unsigned 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                (unsigned int)(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 cnum1, cnum2, cnum3;
669         uint16 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 offset;
1035         BOOL correct = True;
1036
1037 #define NEXT_OFFSET offset += (~(uint32)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 static BOOL run_maxfidtest(struct cli_state *cli, int dummy)
1764 {
1765         const char *template = "\\maxfid.%d.%d";
1766         char *fname;
1767         int fnums[0x11000], i;
1768         int retries=4;
1769         BOOL correct = True;
1770
1771         if (retries <= 0) {
1772                 printf("failed to connect\n");
1773                 return False;
1774         }
1775
1776         printf("Testing maximum number of open files\n");
1777
1778         for (i=0; i<0x11000; i++) {
1779                 asprintf(&fname, template, i,(int)getpid());
1780                 if ((fnums[i] = cli_open(cli->tree, fname, 
1781                                         O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) ==
1782                     -1) {
1783                         printf("open of %s failed (%s)\n", 
1784                                fname, cli_errstr(cli->tree));
1785                         printf("maximum fnum is %d\n", i);
1786                         break;
1787                 }
1788                 free(fname);
1789                 printf("%6d\r", i);
1790         }
1791         printf("%6d\n", i);
1792         i--;
1793
1794         printf("cleaning up\n");
1795         for (;i>=0;i--) {
1796                 asprintf(&fname, template, i,(int)getpid());
1797                 if (NT_STATUS_IS_ERR(cli_close(cli->tree, fnums[i]))) {
1798                         printf("Close of fnum %d failed - %s\n", fnums[i], cli_errstr(cli->tree));
1799                 }
1800                 if (NT_STATUS_IS_ERR(cli_unlink(cli->tree, fname))) {
1801                         printf("unlink of %s failed (%s)\n", 
1802                                fname, cli_errstr(cli->tree));
1803                         correct = False;
1804                 }
1805                 free(fname);
1806                 printf("%6d\r", i);
1807         }
1808         printf("%6d\n", 0);
1809
1810         printf("maxfid test finished\n");
1811         if (!torture_close_connection(cli)) {
1812                 correct = False;
1813         }
1814         return correct;
1815 }
1816
1817 /* send smb negprot commands, not reading the response */
1818 static BOOL run_negprot_nowait(int dummy)
1819 {
1820         int i;
1821         struct cli_state *cli;
1822         BOOL correct = True;
1823
1824         printf("starting negprot nowait test\n");
1825
1826         cli = open_nbt_connection();
1827         if (!cli) {
1828                 return False;
1829         }
1830
1831         printf("Establishing protocol negotiations - connect with another client\n");
1832
1833         for (i=0;i<50000;i++) {
1834                 smb_negprot_send(cli->transport, PROTOCOL_NT1);
1835         }
1836
1837         if (!torture_close_connection(cli)) {
1838                 correct = False;
1839         }
1840
1841         printf("finished negprot nowait test\n");
1842
1843         return correct;
1844 }
1845
1846
1847 /*
1848   This checks how the getatr calls works
1849 */
1850 static BOOL run_attrtest(int dummy)
1851 {
1852         struct cli_state *cli;
1853         int fnum;
1854         time_t t, t2;
1855         const char *fname = "\\attrib123456789.tst";
1856         BOOL correct = True;
1857
1858         printf("starting attrib test\n");
1859
1860         if (!torture_open_connection(&cli)) {
1861                 return False;
1862         }
1863
1864         cli_unlink(cli->tree, fname);
1865         fnum = cli_open(cli->tree, fname, 
1866                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1867         cli_close(cli->tree, fnum);
1868
1869         if (NT_STATUS_IS_ERR(cli_getatr(cli->tree, fname, NULL, NULL, &t))) {
1870                 printf("getatr failed (%s)\n", cli_errstr(cli->tree));
1871                 correct = False;
1872         }
1873
1874         printf("New file time is %s", ctime(&t));
1875
1876         if (abs(t - time(NULL)) > 60*60*24*10) {
1877                 printf("ERROR: SMBgetatr bug. time is %s",
1878                        ctime(&t));
1879                 t = time(NULL);
1880                 correct = False;
1881         }
1882
1883         t2 = t-60*60*24; /* 1 day ago */
1884
1885         printf("Setting file time to %s", ctime(&t2));
1886
1887         if (NT_STATUS_IS_ERR(cli_setatr(cli->tree, fname, 0, t2))) {
1888                 printf("setatr failed (%s)\n", cli_errstr(cli->tree));
1889                 correct = True;
1890         }
1891
1892         if (NT_STATUS_IS_ERR(cli_getatr(cli->tree, fname, NULL, NULL, &t))) {
1893                 printf("getatr failed (%s)\n", cli_errstr(cli->tree));
1894                 correct = True;
1895         }
1896
1897         printf("Retrieved file time as %s", ctime(&t));
1898
1899         if (t != t2) {
1900                 printf("ERROR: getatr/setatr bug. times are\n%s",
1901                        ctime(&t));
1902                 printf("%s", ctime(&t2));
1903                 correct = True;
1904         }
1905
1906         cli_unlink(cli->tree, fname);
1907
1908         if (!torture_close_connection(cli)) {
1909                 correct = False;
1910         }
1911
1912         printf("attrib test finished\n");
1913
1914         return correct;
1915 }
1916
1917
1918 /*
1919   This checks a couple of trans2 calls
1920 */
1921 static BOOL run_trans2test(int dummy)
1922 {
1923         struct cli_state *cli;
1924         int fnum;
1925         size_t size;
1926         time_t c_time, a_time, m_time, w_time, m_time2;
1927         const char *fname = "\\trans2.tst";
1928         const char *dname = "\\trans2";
1929         const char *fname2 = "\\trans2\\trans2.tst";
1930         const char *pname;
1931         BOOL correct = True;
1932
1933         printf("starting trans2 test\n");
1934
1935         if (!torture_open_connection(&cli)) {
1936                 return False;
1937         }
1938
1939         cli_unlink(cli->tree, fname);
1940
1941         printf("Testing qfileinfo\n");
1942         
1943         fnum = cli_open(cli->tree, fname, 
1944                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1945         if (NT_STATUS_IS_ERR(cli_qfileinfo(cli->tree, fnum, NULL, &size, &c_time, &a_time, &m_time,
1946                            NULL, NULL))) {
1947                 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(cli->tree));
1948                 correct = False;
1949         }
1950
1951         printf("Testing NAME_INFO\n");
1952
1953         if (NT_STATUS_IS_ERR(cli_qfilename(cli->tree, fnum, &pname))) {
1954                 printf("ERROR: qfilename failed (%s)\n", cli_errstr(cli->tree));
1955                 correct = False;
1956         }
1957
1958         if (!pname || strcmp(pname, fname)) {
1959                 printf("qfilename gave different name? [%s] [%s]\n",
1960                        fname, pname);
1961                 correct = False;
1962         }
1963
1964         cli_close(cli->tree, fnum);
1965         cli_unlink(cli->tree, fname);
1966
1967         fnum = cli_open(cli->tree, fname, 
1968                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1969         if (fnum == -1) {
1970                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli->tree));
1971                 return False;
1972         }
1973         cli_close(cli->tree, fnum);
1974
1975         printf("Checking for sticky create times\n");
1976
1977         if (NT_STATUS_IS_ERR(cli_qpathinfo(cli->tree, fname, &c_time, &a_time, &m_time, &size, NULL))) {
1978                 printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(cli->tree));
1979                 correct = False;
1980         } else {
1981                 if (c_time != m_time) {
1982                         printf("create time=%s", ctime(&c_time));
1983                         printf("modify time=%s", ctime(&m_time));
1984                         printf("This system appears to have sticky create times\n");
1985                 }
1986                 if (a_time % (60*60) == 0) {
1987                         printf("access time=%s", ctime(&a_time));
1988                         printf("This system appears to set a midnight access time\n");
1989                         correct = False;
1990                 }
1991
1992                 if (abs(m_time - time(NULL)) > 60*60*24*7) {
1993                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
1994                         correct = False;
1995                 }
1996         }
1997
1998
1999         cli_unlink(cli->tree, fname);
2000         fnum = cli_open(cli->tree, fname, 
2001                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2002         cli_close(cli->tree, fnum);
2003         if (NT_STATUS_IS_ERR(cli_qpathinfo2(cli->tree, fname, &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
2004                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(cli->tree));
2005                 correct = False;
2006         } else {
2007                 if (w_time < 60*60*24*2) {
2008                         printf("write time=%s", ctime(&w_time));
2009                         printf("This system appears to set a initial 0 write time\n");
2010                         correct = False;
2011                 }
2012         }
2013
2014         cli_unlink(cli->tree, fname);
2015
2016
2017         /* check if the server updates the directory modification time
2018            when creating a new file */
2019         if (NT_STATUS_IS_ERR(cli_mkdir(cli->tree, dname))) {
2020                 printf("ERROR: mkdir failed (%s)\n", cli_errstr(cli->tree));
2021                 correct = False;
2022         }
2023         sleep(3);
2024         if (NT_STATUS_IS_ERR(cli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
2025                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(cli->tree));
2026                 correct = False;
2027         }
2028
2029         fnum = cli_open(cli->tree, fname2, 
2030                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2031         cli_write(cli->tree, fnum,  0, (char *)&fnum, 0, sizeof(fnum));
2032         cli_close(cli->tree, fnum);
2033         if (NT_STATUS_IS_ERR(cli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time2, &w_time, &size, NULL, NULL))) {
2034                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(cli->tree));
2035                 correct = False;
2036         } else {
2037                 if (m_time2 == m_time) {
2038                         printf("This system does not update directory modification times\n");
2039                         correct = False;
2040                 }
2041         }
2042         cli_unlink(cli->tree, fname2);
2043         cli_rmdir(cli->tree, dname);
2044
2045         if (!torture_close_connection(cli)) {
2046                 correct = False;
2047         }
2048
2049         printf("trans2 test finished\n");
2050
2051         return correct;
2052 }
2053
2054 /*
2055   Test delete on close semantics.
2056  */
2057 static BOOL run_deletetest(int dummy)
2058 {
2059         struct cli_state *cli1;
2060         struct cli_state *cli2 = NULL;
2061         const char *fname = "\\delete.file";
2062         int fnum1 = -1;
2063         int fnum2 = -1;
2064         BOOL correct = True;
2065         
2066         printf("starting delete test\n");
2067         
2068         if (!torture_open_connection(&cli1)) {
2069                 return False;
2070         }
2071         
2072         /* Test 1 - this should delete the file on close. */
2073         
2074         cli_setatr(cli1->tree, fname, 0, 0);
2075         cli_unlink(cli1->tree, fname);
2076         
2077         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
2078                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 
2079                                    NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2080         
2081         if (fnum1 == -1) {
2082                 printf("[1] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2083                 correct = False;
2084                 goto fail;
2085         }
2086         
2087         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2088                 printf("[1] close failed (%s)\n", cli_errstr(cli1->tree));
2089                 correct = False;
2090                 goto fail;
2091         }
2092
2093         fnum1 = cli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
2094         if (fnum1 != -1) {
2095                 printf("[1] open of %s succeeded (should fail)\n", fname);
2096                 correct = False;
2097                 goto fail;
2098         }
2099         
2100         printf("first delete on close test succeeded.\n");
2101         
2102         /* Test 2 - this should delete the file on close. */
2103         
2104         cli_setatr(cli1->tree, fname, 0, 0);
2105         cli_unlink(cli1->tree, fname);
2106         
2107         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS,
2108                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, 
2109                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2110         
2111         if (fnum1 == -1) {
2112                 printf("[2] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2113                 correct = False;
2114                 goto fail;
2115         }
2116         
2117         if (NT_STATUS_IS_ERR(cli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2118                 printf("[2] setting delete_on_close failed (%s)\n", cli_errstr(cli1->tree));
2119                 correct = False;
2120                 goto fail;
2121         }
2122         
2123         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2124                 printf("[2] close failed (%s)\n", cli_errstr(cli1->tree));
2125                 correct = False;
2126                 goto fail;
2127         }
2128         
2129         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2130         if (fnum1 != -1) {
2131                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
2132                 if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2133                         printf("[2] close failed (%s)\n", cli_errstr(cli1->tree));
2134                         correct = False;
2135                         goto fail;
2136                 }
2137                 cli_unlink(cli1->tree, fname);
2138         } else
2139                 printf("second delete on close test succeeded.\n");
2140         
2141         /* Test 3 - ... */
2142         cli_setatr(cli1->tree, fname, 0, 0);
2143         cli_unlink(cli1->tree, fname);
2144
2145         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
2146                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2147
2148         if (fnum1 == -1) {
2149                 printf("[3] open - 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2150                 correct = False;
2151                 goto fail;
2152         }
2153
2154         /* This should fail with a sharing violation - open for delete is only compatible
2155            with SHARE_DELETE. */
2156
2157         fnum2 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
2158                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
2159                                    NTCREATEX_DISP_OPEN, 0, 0);
2160
2161         if (fnum2 != -1) {
2162                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
2163                 correct = False;
2164                 goto fail;
2165         }
2166
2167         /* This should succeed. */
2168
2169         fnum2 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
2170                         NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN, 0, 0);
2171
2172         if (fnum2 == -1) {
2173                 printf("[3] open  - 2 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2174                 correct = False;
2175                 goto fail;
2176         }
2177
2178         if (NT_STATUS_IS_ERR(cli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2179                 printf("[3] setting delete_on_close failed (%s)\n", cli_errstr(cli1->tree));
2180                 correct = False;
2181                 goto fail;
2182         }
2183         
2184         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2185                 printf("[3] close 1 failed (%s)\n", cli_errstr(cli1->tree));
2186                 correct = False;
2187                 goto fail;
2188         }
2189         
2190         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum2))) {
2191                 printf("[3] close 2 failed (%s)\n", cli_errstr(cli1->tree));
2192                 correct = False;
2193                 goto fail;
2194         }
2195         
2196         /* This should fail - file should no longer be there. */
2197
2198         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2199         if (fnum1 != -1) {
2200                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
2201                 if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2202                         printf("[3] close failed (%s)\n", cli_errstr(cli1->tree));
2203                 }
2204                 cli_unlink(cli1->tree, fname);
2205                 correct = False;
2206                 goto fail;
2207         } else
2208                 printf("third delete on close test succeeded.\n");
2209
2210         /* Test 4 ... */
2211         cli_setatr(cli1->tree, fname, 0, 0);
2212         cli_unlink(cli1->tree, fname);
2213
2214         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, 
2215                                    SA_RIGHT_FILE_READ_DATA  | 
2216                                    SA_RIGHT_FILE_WRITE_DATA |
2217                                    STD_RIGHT_DELETE_ACCESS,
2218                                    FILE_ATTRIBUTE_NORMAL, 
2219                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
2220                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2221                                                                 
2222         if (fnum1 == -1) {
2223                 printf("[4] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2224                 correct = False;
2225                 goto fail;
2226         }
2227
2228         /* This should succeed. */
2229         fnum2 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ,
2230                                    FILE_ATTRIBUTE_NORMAL, 
2231                                    NTCREATEX_SHARE_ACCESS_READ  | 
2232                                    NTCREATEX_SHARE_ACCESS_WRITE |
2233                                    NTCREATEX_SHARE_ACCESS_DELETE, 
2234                                    NTCREATEX_DISP_OPEN, 0, 0);
2235         if (fnum2 == -1) {
2236                 printf("[4] open  - 2 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2237                 correct = False;
2238                 goto fail;
2239         }
2240         
2241         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum2))) {
2242                 printf("[4] close - 1 failed (%s)\n", cli_errstr(cli1->tree));
2243                 correct = False;
2244                 goto fail;
2245         }
2246         
2247         if (NT_STATUS_IS_ERR(cli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2248                 printf("[4] setting delete_on_close failed (%s)\n", cli_errstr(cli1->tree));
2249                 correct = False;
2250                 goto fail;
2251         }
2252         
2253         /* This should fail - no more opens once delete on close set. */
2254         fnum2 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ,
2255                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
2256                                    NTCREATEX_DISP_OPEN, 0, 0);
2257         if (fnum2 != -1) {
2258                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
2259                 correct = False;
2260                 goto fail;
2261         } else
2262                 printf("fourth delete on close test succeeded.\n");
2263         
2264         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2265                 printf("[4] close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2266                 correct = False;
2267                 goto fail;
2268         }
2269         
2270         /* Test 5 ... */
2271         cli_setatr(cli1->tree, fname, 0, 0);
2272         cli_unlink(cli1->tree, fname);
2273         
2274         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2275         if (fnum1 == -1) {
2276                 printf("[5] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2277                 correct = False;
2278                 goto fail;
2279         }
2280
2281         /* This should fail - only allowed on NT opens with DELETE access. */
2282
2283         if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2284                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
2285                 correct = False;
2286                 goto fail;
2287         }
2288
2289         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2290                 printf("[5] close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2291                 correct = False;
2292                 goto fail;
2293         }
2294         
2295         printf("fifth delete on close test succeeded.\n");
2296         
2297         /* Test 6 ... */
2298         cli_setatr(cli1->tree, fname, 0, 0);
2299         cli_unlink(cli1->tree, fname);
2300         
2301         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, 
2302                                    SA_RIGHT_FILE_READ_DATA | SA_RIGHT_FILE_WRITE_DATA,
2303                                    FILE_ATTRIBUTE_NORMAL, 
2304                                    NTCREATEX_SHARE_ACCESS_READ  |
2305                                    NTCREATEX_SHARE_ACCESS_WRITE |
2306                                    NTCREATEX_SHARE_ACCESS_DELETE,
2307                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2308         
2309         if (fnum1 == -1) {
2310                 printf("[6] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2311                 correct = False;
2312                 goto fail;
2313         }
2314         
2315         /* This should fail - only allowed on NT opens with DELETE access. */
2316         
2317         if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2318                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
2319                 correct = False;
2320                 goto fail;
2321         }
2322
2323         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2324                 printf("[6] close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2325                 correct = False;
2326                 goto fail;
2327         }
2328
2329         printf("sixth delete on close test succeeded.\n");
2330         
2331         /* Test 7 ... */
2332         cli_setatr(cli1->tree, fname, 0, 0);
2333         cli_unlink(cli1->tree, fname);
2334         
2335         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, 
2336                                    SA_RIGHT_FILE_READ_DATA  | 
2337                                    SA_RIGHT_FILE_WRITE_DATA |
2338                                    STD_RIGHT_DELETE_ACCESS,
2339                                    FILE_ATTRIBUTE_NORMAL, 0, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2340                                                                 
2341         if (fnum1 == -1) {
2342                 printf("[7] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2343                 correct = False;
2344                 goto fail;
2345         }
2346
2347         if (NT_STATUS_IS_ERR(cli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2348                 printf("[7] setting delete_on_close on file failed !\n");
2349                 correct = False;
2350                 goto fail;
2351         }
2352         
2353         if (NT_STATUS_IS_ERR(cli_nt_delete_on_close(cli1->tree, fnum1, False))) {
2354                 printf("[7] unsetting delete_on_close on file failed !\n");
2355                 correct = False;
2356                 goto fail;
2357         }
2358
2359         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2360                 printf("[7] close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2361                 correct = False;
2362                 goto fail;
2363         }
2364         
2365         /* This next open should succeed - we reset the flag. */
2366         
2367         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2368         if (fnum1 == -1) {
2369                 printf("[5] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2370                 correct = False;
2371                 goto fail;
2372         }
2373
2374         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2375                 printf("[7] close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2376                 correct = False;
2377                 goto fail;
2378         }
2379
2380         printf("seventh delete on close test succeeded.\n");
2381         
2382         /* Test 7 ... */
2383         cli_setatr(cli1->tree, fname, 0, 0);
2384         cli_unlink(cli1->tree, fname);
2385         
2386         if (!torture_open_connection(&cli2)) {
2387                 printf("[8] failed to open second connection.\n");
2388                 correct = False;
2389                 goto fail;
2390         }
2391
2392         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|STD_RIGHT_DELETE_ACCESS,
2393                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
2394                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2395         
2396         if (fnum1 == -1) {
2397                 printf("[8] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2398                 correct = False;
2399                 goto fail;
2400         }
2401
2402         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|STD_RIGHT_DELETE_ACCESS,
2403                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
2404                                    NTCREATEX_DISP_OPEN, 0, 0);
2405         
2406         if (fnum2 == -1) {
2407                 printf("[8] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2408                 correct = False;
2409                 goto fail;
2410         }
2411
2412         if (NT_STATUS_IS_ERR(cli_nt_delete_on_close(cli1->tree, fnum1, True))) {
2413                 printf("[8] setting delete_on_close on file failed !\n");
2414                 correct = False;
2415                 goto fail;
2416         }
2417         
2418         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2419                 printf("[8] close - 1 failed (%s)\n", cli_errstr(cli1->tree));
2420                 correct = False;
2421                 goto fail;
2422         }
2423
2424         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum2))) {
2425                 printf("[8] close - 2 failed (%s)\n", cli_errstr(cli2->tree));
2426                 correct = False;
2427                 goto fail;
2428         }
2429
2430         /* This should fail.. */
2431         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2432         if (fnum1 != -1) {
2433                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
2434                 goto fail;
2435                 correct = False;
2436         } else
2437                 printf("eighth delete on close test succeeded.\n");
2438
2439         /* This should fail - we need to set DELETE_ACCESS. */
2440         fnum1 = cli_nt_create_full(cli1->tree, fname, 0,SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA,
2441                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2442         
2443         if (fnum1 != -1) {
2444                 printf("[9] open of %s succeeded should have failed!\n", fname);
2445                 correct = False;
2446                 goto fail;
2447         }
2448
2449         printf("ninth delete on close test succeeded.\n");
2450
2451         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|STD_RIGHT_DELETE_ACCESS,
2452                                    FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2453         if (fnum1 == -1) {
2454                 printf("[10] open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2455                 correct = False;
2456                 goto fail;
2457         }
2458
2459         /* This should delete the file. */
2460         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2461                 printf("[10] close failed (%s)\n", cli_errstr(cli1->tree));
2462                 correct = False;
2463                 goto fail;
2464         }
2465
2466         /* This should fail.. */
2467         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
2468         if (fnum1 != -1) {
2469                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
2470                 goto fail;
2471                 correct = False;
2472         } else
2473                 printf("tenth delete on close test succeeded.\n");
2474         printf("finished delete test\n");
2475
2476   fail:
2477         /* FIXME: This will crash if we aborted before cli2 got
2478          * intialized, because these functions don't handle
2479          * uninitialized connections. */
2480                 
2481         cli_close(cli1->tree, fnum1);
2482         cli_close(cli1->tree, fnum2);
2483         cli_setatr(cli1->tree, fname, 0, 0);
2484         cli_unlink(cli1->tree, fname);
2485
2486         if (!torture_close_connection(cli1)) {
2487                 correct = False;
2488         }
2489         if (!torture_close_connection(cli2)) {
2490                 correct = False;
2491         }
2492         return correct;
2493 }
2494
2495
2496 /*
2497   print out server properties
2498  */
2499 static BOOL run_properties(int dummy)
2500 {
2501         struct cli_state *cli;
2502         BOOL correct = True;
2503         
2504         printf("starting properties test\n");
2505         
2506         ZERO_STRUCT(cli);
2507
2508         if (!torture_open_connection(&cli)) {
2509                 return False;
2510         }
2511         
2512         d_printf("Capabilities 0x%08x\n", cli->transport->negotiate.capabilities);
2513
2514         if (!torture_close_connection(cli)) {
2515                 correct = False;
2516         }
2517
2518         return correct;
2519 }
2520
2521
2522
2523 /* FIRST_DESIRED_ACCESS   0xf019f */
2524 #define FIRST_DESIRED_ACCESS   SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|SA_RIGHT_FILE_APPEND_DATA|\
2525                                SA_RIGHT_FILE_READ_EA|                           /* 0xf */ \
2526                                SA_RIGHT_FILE_WRITE_EA|SA_RIGHT_FILE_READ_ATTRIBUTES|     /* 0x90 */ \
2527                                SA_RIGHT_FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
2528                                STD_RIGHT_DELETE_ACCESS|STD_RIGHT_READ_CONTROL_ACCESS|\
2529                                STD_RIGHT_WRITE_DAC_ACCESS|STD_RIGHT_WRITE_OWNER_ACCESS     /* 0xf0000 */
2530 /* SECOND_DESIRED_ACCESS  0xe0080 */
2531 #define SECOND_DESIRED_ACCESS  SA_RIGHT_FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
2532                                STD_RIGHT_READ_CONTROL_ACCESS|STD_RIGHT_WRITE_DAC_ACCESS|\
2533                                STD_RIGHT_WRITE_OWNER_ACCESS                      /* 0xe0000 */
2534
2535 #if 0
2536 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
2537                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
2538                                SA_RIGHT_FILE_READ_DATA|\
2539                                WRITE_OWNER_ACCESS                      /* */
2540 #endif
2541
2542 /*
2543   Test ntcreate calls made by xcopy
2544  */
2545 static BOOL run_xcopy(int dummy)
2546 {
2547         struct cli_state *cli1;
2548         const char *fname = "\\test.txt";
2549         BOOL correct = True;
2550         int fnum1, fnum2;
2551
2552         printf("starting xcopy test\n");
2553         
2554         if (!torture_open_connection(&cli1)) {
2555                 return False;
2556         }
2557         
2558         fnum1 = cli_nt_create_full(cli1->tree, fname, 0,
2559                                    FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
2560                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 
2561                                    0x4044, 0);
2562
2563         if (fnum1 == -1) {
2564                 printf("First open failed - %s\n", cli_errstr(cli1->tree));
2565                 return False;
2566         }
2567
2568         fnum2 = cli_nt_create_full(cli1->tree, fname, 0,
2569                                    SECOND_DESIRED_ACCESS, 0,
2570                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN, 
2571                                    0x200000, 0);
2572         if (fnum2 == -1) {
2573                 printf("second open failed - %s\n", cli_errstr(cli1->tree));
2574                 return False;
2575         }
2576         
2577         if (!torture_close_connection(cli1)) {
2578                 correct = False;
2579         }
2580         
2581         return correct;
2582 }
2583
2584 /*
2585   Test rename on files open with share delete and no share delete.
2586  */
2587 static BOOL run_rename(int dummy)
2588 {
2589         struct cli_state *cli1;
2590         const char *fname = "\\test.txt";
2591         const char *fname1 = "\\test1.txt";
2592         BOOL correct = True;
2593         int fnum1;
2594
2595         printf("starting rename test\n");
2596         
2597         if (!torture_open_connection(&cli1)) {
2598                 return False;
2599         }
2600         
2601         cli_unlink(cli1->tree, fname);
2602         cli_unlink(cli1->tree, fname1);
2603         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
2604                                    NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2605
2606         if (fnum1 == -1) {
2607                 printf("First open failed - %s\n", cli_errstr(cli1->tree));
2608                 return False;
2609         }
2610
2611         if (NT_STATUS_IS_ERR(cli_rename(cli1->tree, fname, fname1))) {
2612                 printf("First rename failed (this is correct) - %s\n", cli_errstr(cli1->tree));
2613         } else {
2614                 printf("First rename succeeded - this should have failed !\n");
2615                 correct = False;
2616         }
2617
2618         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2619                 printf("close - 1 failed (%s)\n", cli_errstr(cli1->tree));
2620                 return False;
2621         }
2622
2623         cli_unlink(cli1->tree, fname);
2624         cli_unlink(cli1->tree, fname1);
2625         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
2626 #if 0
2627                                    NTCREATEX_SHARE_ACCESS_DELETE|NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2628 #else
2629                                    NTCREATEX_SHARE_ACCESS_DELETE|NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2630 #endif
2631
2632         if (fnum1 == -1) {
2633                 printf("Second open failed - %s\n", cli_errstr(cli1->tree));
2634                 return False;
2635         }
2636
2637         if (NT_STATUS_IS_ERR(cli_rename(cli1->tree, fname, fname1))) {
2638                 printf("Second rename failed - this should have succeeded - %s\n", cli_errstr(cli1->tree));
2639                 correct = False;
2640         } else {
2641                 printf("Second rename succeeded\n");
2642         }
2643
2644         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2645                 printf("close - 2 failed (%s)\n", cli_errstr(cli1->tree));
2646                 return False;
2647         }
2648
2649         cli_unlink(cli1->tree, fname);
2650         cli_unlink(cli1->tree, fname1);
2651
2652         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_READ_CONTROL_ACCESS, FILE_ATTRIBUTE_NORMAL,
2653                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2654
2655         if (fnum1 == -1) {
2656                 printf("Third open failed - %s\n", cli_errstr(cli1->tree));
2657                 return False;
2658         }
2659
2660
2661 #if 0
2662   {
2663   int fnum2;
2664
2665         fnum2 = cli_nt_create_full(cli1->tree, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
2666                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2667
2668         if (fnum2 == -1) {
2669                 printf("Fourth open failed - %s\n", cli_errstr(cli1->tree));
2670                 return False;
2671         }
2672         if (!cli_nt_delete_on_close(cli1->tree, fnum2, True)) {
2673                 printf("[8] setting delete_on_close on file failed !\n");
2674                 return False;
2675         }
2676         
2677         if (!cli_close(cli1->tree, fnum2)) {
2678                 printf("close - 4 failed (%s)\n", cli_errstr(cli1->tree));
2679                 return False;
2680         }
2681   }
2682 #endif
2683
2684         if (NT_STATUS_IS_ERR(cli_rename(cli1->tree, fname, fname1))) {
2685                 printf("Third rename failed - this should have succeeded - %s\n", cli_errstr(cli1->tree));
2686                 correct = False;
2687         } else {
2688                 printf("Third rename succeeded\n");
2689         }
2690
2691         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2692                 printf("close - 3 failed (%s)\n", cli_errstr(cli1->tree));
2693                 return False;
2694         }
2695
2696         cli_unlink(cli1->tree, fname);
2697         cli_unlink(cli1->tree, fname1);
2698
2699         if (!torture_close_connection(cli1)) {
2700                 correct = False;
2701         }
2702         
2703         return correct;
2704 }
2705
2706 static BOOL run_pipe_number(int dummy)
2707 {
2708         struct cli_state *cli1;
2709         const char *pipe_name = "\\WKSSVC";
2710         int fnum;
2711         int num_pipes = 0;
2712
2713         printf("starting pipenumber test\n");
2714         if (!torture_open_connection(&cli1)) {
2715                 return False;
2716         }
2717
2718         while(1) {
2719                 fnum = cli_nt_create_full(cli1->tree, pipe_name, 0, SA_RIGHT_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
2720                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OPEN_IF, 0, 0);
2721
2722                 if (fnum == -1) {
2723                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, cli_errstr(cli1->tree));
2724                         break;
2725                 }
2726                 num_pipes++;
2727         }
2728
2729         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
2730         torture_close_connection(cli1);
2731         return True;
2732 }
2733
2734
2735
2736
2737 /*
2738   open N connections to the server and just hold them open
2739   used for testing performance when there are N idle users
2740   already connected
2741  */
2742  static BOOL torture_holdcon(int dummy)
2743 {
2744         int i;
2745         struct cli_state **cli;
2746         int num_dead = 0;
2747
2748         printf("Opening %d connections\n", torture_numops);
2749         
2750         cli = malloc(sizeof(struct cli_state *) * torture_numops);
2751
2752         for (i=0;i<torture_numops;i++) {
2753                 if (!torture_open_connection(&cli[i])) {
2754                         return False;
2755                 }
2756                 printf("opened %d connections\r", i);
2757                 fflush(stdout);
2758         }
2759
2760         printf("\nStarting pings\n");
2761
2762         while (1) {
2763                 for (i=0;i<torture_numops;i++) {
2764                         NTSTATUS status;
2765                         if (cli[i]) {
2766                                 status = cli_chkpath(cli[i]->tree, "\\");
2767                                 if (!NT_STATUS_IS_OK(status)) {
2768                                         printf("Connection %d is dead\n", i);
2769                                         cli[i] = NULL;
2770                                         num_dead++;
2771                                 }
2772                                 usleep(100);
2773                         }
2774                 }
2775
2776                 if (num_dead == torture_numops) {
2777                         printf("All connections dead - finishing\n");
2778                         break;
2779                 }
2780
2781                 printf(".");
2782                 fflush(stdout);
2783         }
2784
2785         return True;
2786 }
2787
2788 /*
2789   Try with a wrong vuid and check error message.
2790  */
2791
2792 static BOOL run_vuidtest(int dummy)
2793 {
2794         struct cli_state *cli;
2795         const char *fname = "\\vuid.tst";
2796         int fnum;
2797         size_t size;
2798         time_t c_time, a_time, m_time, w_time, m_time2;
2799         BOOL correct = True;
2800
2801         uint16 orig_vuid;
2802         NTSTATUS result;
2803
2804         printf("starting vuid test\n");
2805
2806         if (!torture_open_connection(&cli)) {
2807                 return False;
2808         }
2809
2810         cli_unlink(cli->tree, fname);
2811
2812         fnum = cli_open(cli->tree, fname, 
2813                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2814
2815         orig_vuid = cli->session->vuid;
2816
2817         cli->session->vuid += 1234;
2818
2819         printf("Testing qfileinfo with wrong vuid\n");
2820         
2821         if (NT_STATUS_IS_OK(result = cli_qfileinfo(cli->tree, fnum, NULL,
2822                                                    &size, &c_time, &a_time,
2823                                                    &m_time, NULL, NULL))) {
2824                 printf("ERROR: qfileinfo passed with wrong vuid\n");
2825                 correct = False;
2826         }
2827
2828         if ( (cli->transport->error.etype != ETYPE_DOS) ||
2829              (cli->transport->error.e.dos.eclass != ERRSRV) ||
2830              (cli->transport->error.e.dos.ecode != ERRbaduid) ) {
2831                 printf("ERROR: qfileinfo should have returned DOS error "
2832                        "ERRSRV:ERRbaduid\n  but returned %s\n",
2833                        cli_errstr(cli->tree));
2834                 correct = False;
2835         }
2836
2837         cli->session->vuid -= 1234;
2838
2839         if (NT_STATUS_IS_ERR(cli_close(cli->tree, fnum))) {
2840                 printf("close failed (%s)\n", cli_errstr(cli->tree));
2841                 correct = False;
2842         }
2843
2844         cli_unlink(cli->tree, fname);
2845
2846         if (!torture_close_connection(cli)) {
2847                 correct = False;
2848         }
2849
2850         printf("vuid test finished\n");
2851
2852         return correct;
2853 }
2854
2855 /*
2856   Test open mode returns on read-only files.
2857  */
2858  static BOOL run_opentest(int dummy)
2859 {
2860         static struct cli_state *cli1;
2861         static struct cli_state *cli2;
2862         const char *fname = "\\readonly.file";
2863         int fnum1, fnum2;
2864         char buf[20];
2865         size_t fsize;
2866         BOOL correct = True;
2867         char *tmp_path;
2868         int failures = 0;
2869
2870         printf("starting open test\n");
2871         
2872         if (!torture_open_connection(&cli1)) {
2873                 return False;
2874         }
2875         
2876         cli_setatr(cli1->tree, fname, 0, 0);
2877         cli_unlink(cli1->tree, fname);
2878         
2879         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
2880         if (fnum1 == -1) {
2881                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2882                 return False;
2883         }
2884
2885         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2886                 printf("close2 failed (%s)\n", cli_errstr(cli1->tree));
2887                 return False;
2888         }
2889         
2890         if (NT_STATUS_IS_ERR(cli_setatr(cli1->tree, fname, FILE_ATTRIBUTE_READONLY, 0))) {
2891                 printf("cli_setatr failed (%s)\n", cli_errstr(cli1->tree));
2892                 CHECK_MAX_FAILURES(error_test1);
2893                 return False;
2894         }
2895         
2896         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
2897         if (fnum1 == -1) {
2898                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2899                 CHECK_MAX_FAILURES(error_test1);
2900                 return False;
2901         }
2902         
2903         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
2904         fnum2 = cli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
2905         
2906         if (check_error(__LINE__, cli1, ERRDOS, ERRnoaccess, 
2907                         NT_STATUS_ACCESS_DENIED)) {
2908                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
2909         }
2910         
2911         printf("finished open test 1\n");
2912 error_test1:
2913         cli_close(cli1->tree, fnum1);
2914         
2915         /* Now try not readonly and ensure ERRbadshare is returned. */
2916         
2917         cli_setatr(cli1->tree, fname, 0, 0);
2918         
2919         fnum1 = cli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
2920         if (fnum1 == -1) {
2921                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2922                 return False;
2923         }
2924         
2925         /* This will fail - but the error should be ERRshare. */
2926         fnum2 = cli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
2927         
2928         if (check_error(__LINE__, cli1, ERRDOS, ERRbadshare, 
2929                         NT_STATUS_SHARING_VIOLATION)) {
2930                 printf("correct error code ERRDOS/ERRbadshare returned\n");
2931         }
2932         
2933         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2934                 printf("close2 failed (%s)\n", cli_errstr(cli1->tree));
2935                 return False;
2936         }
2937         
2938         cli_unlink(cli1->tree, fname);
2939         
2940         printf("finished open test 2\n");
2941         
2942         /* Test truncate open disposition on file opened for read. */
2943         
2944         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
2945         if (fnum1 == -1) {
2946                 printf("(3) open (1) of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2947                 return False;
2948         }
2949         
2950         /* write 20 bytes. */
2951         
2952         memset(buf, '\0', 20);
2953
2954         if (cli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
2955                 printf("write failed (%s)\n", cli_errstr(cli1->tree));
2956                 correct = False;
2957         }
2958
2959         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2960                 printf("(3) close1 failed (%s)\n", cli_errstr(cli1->tree));
2961                 return False;
2962         }
2963         
2964         /* Ensure size == 20. */
2965         if (NT_STATUS_IS_ERR(cli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
2966                 printf("(3) getatr failed (%s)\n", cli_errstr(cli1->tree));
2967                 CHECK_MAX_FAILURES(error_test3);
2968                 return False;
2969         }
2970         
2971         if (fsize != 20) {
2972                 printf("(3) file size != 20\n");
2973                 CHECK_MAX_FAILURES(error_test3);
2974                 return False;
2975         }
2976
2977         /* Now test if we can truncate a file opened for readonly. */
2978         
2979         fnum1 = cli_open(cli1->tree, fname, O_RDONLY|O_TRUNC, DENY_NONE);
2980         if (fnum1 == -1) {
2981                 printf("(3) open (2) of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
2982                 CHECK_MAX_FAILURES(error_test3);
2983                 return False;
2984         }
2985         
2986         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
2987                 printf("close2 failed (%s)\n", cli_errstr(cli1->tree));
2988                 return False;
2989         }
2990
2991         /* Ensure size == 0. */
2992         if (NT_STATUS_IS_ERR(cli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
2993                 printf("(3) getatr failed (%s)\n", cli_errstr(cli1->tree));
2994                 CHECK_MAX_FAILURES(error_test3);
2995                 return False;
2996         }
2997
2998         if (fsize != 0) {
2999                 printf("(3) file size != 0\n");
3000                 CHECK_MAX_FAILURES(error_test3);
3001                 return False;
3002         }
3003         printf("finished open test 3\n");
3004 error_test3:    
3005         cli_unlink(cli1->tree, fname);
3006
3007
3008         printf("testing ctemp\n");
3009         fnum1 = cli_ctemp(cli1->tree, "\\", &tmp_path);
3010         if (fnum1 == -1) {
3011                 printf("ctemp failed (%s)\n", cli_errstr(cli1->tree));
3012                 CHECK_MAX_FAILURES(error_test4);
3013                 return False;
3014         }
3015         printf("ctemp gave path %s\n", tmp_path);
3016         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3017                 printf("close of temp failed (%s)\n", cli_errstr(cli1->tree));
3018         }
3019         if (NT_STATUS_IS_ERR(cli_unlink(cli1->tree, tmp_path))) {
3020                 printf("unlink of temp failed (%s)\n", cli_errstr(cli1->tree));
3021         }
3022 error_test4:    
3023         /* Test the non-io opens... */
3024
3025         if (!torture_open_connection(&cli2)) {
3026                 return False;
3027         }
3028         
3029         cli_setatr(cli2->tree, fname, 0, 0);
3030         cli_unlink(cli2->tree, fname);
3031         
3032         printf("TEST #1 testing 2 non-io opens (no delete)\n");
3033         
3034         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3035                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3036
3037         if (fnum1 == -1) {
3038                 printf("test 1 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3039                 CHECK_MAX_FAILURES(error_test10);
3040                 return False;
3041         }
3042
3043         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3044                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3045         if (fnum2 == -1) {
3046                 printf("test 1 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3047                 CHECK_MAX_FAILURES(error_test10);
3048                 return False;
3049         }
3050
3051         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3052                 printf("test 1 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3053                 return False;
3054         }
3055         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum2))) {
3056                 printf("test 1 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3057                 return False;
3058         }
3059
3060         printf("non-io open test #1 passed.\n");
3061 error_test10:
3062         cli_unlink(cli1->tree, fname);
3063
3064         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
3065         
3066         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3067                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3068
3069         if (fnum1 == -1) {
3070                 printf("test 2 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3071                 CHECK_MAX_FAILURES(error_test20);
3072                 return False;
3073         }
3074
3075         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3076                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3077
3078         if (fnum2 == -1) {
3079                 printf("test 2 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3080                 CHECK_MAX_FAILURES(error_test20);
3081                 return False;
3082         }
3083
3084         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3085                 printf("test 1 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3086                 return False;
3087         }
3088         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum2))) {
3089                 printf("test 1 close 2 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3090                 return False;
3091         }
3092
3093         printf("non-io open test #2 passed.\n");
3094 error_test20:
3095         cli_unlink(cli1->tree, fname);
3096
3097         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
3098         
3099         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3100                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3101
3102         if (fnum1 == -1) {
3103                 printf("test 3 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3104                 CHECK_MAX_FAILURES(error_test30);
3105                 return False;
3106         }
3107
3108         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3109                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3110
3111         if (fnum2 == -1) {
3112                 printf("test 3 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3113                 CHECK_MAX_FAILURES(error_test30);
3114                 return False;
3115         }
3116
3117         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3118                 printf("test 3 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3119                 return False;
3120         }
3121         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum2))) {
3122                 printf("test 3 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3123                 return False;
3124         }
3125
3126         printf("non-io open test #3 passed.\n");
3127 error_test30:
3128         cli_unlink(cli1->tree, fname);
3129
3130         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
3131         
3132         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3133                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3134
3135         if (fnum1 == -1) {
3136                 printf("test 4 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3137                 CHECK_MAX_FAILURES(error_test40);
3138                 return False;
3139         }
3140
3141         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3142                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3143
3144         if (fnum2 != -1) {
3145                 printf("test 4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, cli_errstr(cli2->tree));
3146                 CHECK_MAX_FAILURES(error_test40);
3147                 return False;
3148         }
3149
3150         printf("test 4 open 2 of %s gave %s (correct error should be %s)\n", fname, cli_errstr(cli2->tree), "sharing violation");
3151
3152         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3153                 printf("test 4 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3154                 return False;
3155         }
3156
3157         printf("non-io open test #4 passed.\n");
3158 error_test40:
3159         cli_unlink(cli1->tree, fname);
3160
3161         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
3162         
3163         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3164                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3165
3166         if (fnum1 == -1) {
3167                 printf("test 5 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3168                 CHECK_MAX_FAILURES(error_test50);
3169                 return False;
3170         }
3171
3172         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3173                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3174
3175         if (fnum2 == -1) {
3176                 printf("test 5 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3177                 CHECK_MAX_FAILURES(error_test50);
3178                 return False;
3179         }
3180
3181         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3182                 printf("test 5 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3183                 return False;
3184         }
3185
3186         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum2))) {
3187                 printf("test 5 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3188                 return False;
3189         }
3190
3191         printf("non-io open test #5 passed.\n");
3192 error_test50:
3193         printf("TEST #6 testing 1 non-io open, one io open\n");
3194         
3195         cli_unlink(cli1->tree, fname);
3196
3197         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
3198                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3199
3200         if (fnum1 == -1) {
3201                 printf("test 6 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3202                 CHECK_MAX_FAILURES(error_test60);
3203                 return False;
3204         }
3205
3206         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3207                                    NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OPEN_IF, 0, 0);
3208
3209         if (fnum2 == -1) {
3210                 printf("test 6 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3211                 CHECK_MAX_FAILURES(error_test60);
3212                 return False;
3213         }
3214
3215         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3216                 printf("test 6 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3217                 return False;
3218         }
3219
3220         if (NT_STATUS_IS_ERR(cli_close(cli2->tree, fnum2))) {
3221                 printf("test 6 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2->tree));
3222                 return False;
3223         }
3224
3225         printf("non-io open test #6 passed.\n");
3226 error_test60:
3227         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
3228
3229         cli_unlink(cli1->tree, fname);
3230
3231         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
3232                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3233
3234         if (fnum1 == -1) {
3235                 printf("test 7 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3236                 CHECK_MAX_FAILURES(error_test70);
3237                 return False;
3238         }
3239
3240         fnum2 = cli_nt_create_full(cli2->tree, fname, 0, STD_RIGHT_DELETE_ACCESS|SA_RIGHT_FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
3241                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
3242
3243         if (fnum2 != -1) {
3244                 printf("test 7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, cli_errstr(cli2->tree));
3245                 CHECK_MAX_FAILURES(error_test70);
3246                 return False;
3247         }
3248
3249         printf("test 7 open 2 of %s gave %s (correct error should be %s)\n", fname, cli_errstr(cli2->tree), "sharing violation");
3250
3251         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3252                 printf("test 7 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3253                 return False;
3254         }
3255
3256         printf("non-io open test #7 passed.\n");
3257
3258 error_test70:
3259
3260         printf("TEST #8 testing one normal open, followed by lock, followed by open with truncate\n");
3261
3262         cli_unlink(cli1->tree, fname);
3263
3264         fnum1 = cli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
3265         if (fnum1 == -1) {
3266                 printf("(8) open (1) of %s failed (%s)\n", fname, cli_errstr(cli1->tree));
3267                 return False;
3268         }
3269         
3270         /* write 20 bytes. */
3271         
3272         memset(buf, '\0', 20);
3273
3274         if (cli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
3275                 printf("(8) write failed (%s)\n", cli_errstr(cli1->tree));
3276                 correct = False;
3277         }
3278
3279         /* Ensure size == 20. */
3280         if (NT_STATUS_IS_ERR(cli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
3281                 printf("(8) getatr (1) failed (%s)\n", cli_errstr(cli1->tree));
3282                 CHECK_MAX_FAILURES(error_test80);
3283                 return False;
3284         }
3285         
3286         if (fsize != 20) {
3287                 printf("(8) file size != 20\n");
3288                 CHECK_MAX_FAILURES(error_test80);
3289                 return False;
3290         }
3291
3292         /* Get an exclusive lock on the open file. */
3293         if (NT_STATUS_IS_ERR(cli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
3294                 printf("(8) lock1 failed (%s)\n", cli_errstr(cli1->tree));
3295                 CHECK_MAX_FAILURES(error_test80);
3296                 return False;
3297         }
3298
3299         fnum2 = cli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
3300         if (fnum1 == -1) {
3301                 printf("(8) open (2) of %s with truncate failed (%s)\n", fname, cli_errstr(cli1->tree));
3302                 return False;
3303         }
3304
3305         /* Ensure size == 0. */
3306         if (NT_STATUS_IS_ERR(cli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
3307                 printf("(8) getatr (2) failed (%s)\n", cli_errstr(cli1->tree));
3308                 CHECK_MAX_FAILURES(error_test80);
3309                 return False;
3310         }
3311         
3312         if (fsize != 0) {
3313                 printf("(8) file size != 0\n");
3314                 CHECK_MAX_FAILURES(error_test80);
3315                 return False;
3316         }
3317
3318         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3319                 printf("(8) close1 failed (%s)\n", cli_errstr(cli1->tree));
3320                 return False;
3321         }
3322         
3323         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum2))) {
3324                 printf("(8) close1 failed (%s)\n", cli_errstr(cli1->tree));
3325                 return False;
3326         }
3327         
3328 error_test80:
3329
3330         printf("open test #8 passed.\n");
3331
3332         cli_unlink(cli1->tree, fname);
3333
3334         if (!torture_close_connection(cli1)) {
3335                 correct = False;
3336         }
3337         if (!torture_close_connection(cli2)) {
3338                 correct = False;
3339         }
3340         
3341         return correct;
3342 }
3343
3344
3345 static uint32 open_attrs_table[] = {
3346                 FILE_ATTRIBUTE_NORMAL,
3347                 FILE_ATTRIBUTE_ARCHIVE,
3348                 FILE_ATTRIBUTE_READONLY,
3349                 FILE_ATTRIBUTE_HIDDEN,
3350                 FILE_ATTRIBUTE_SYSTEM,
3351
3352                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
3353                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
3354                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
3355                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
3356                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
3357                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
3358
3359                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
3360                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
3361                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
3362                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
3363 };
3364
3365 struct trunc_open_results {
3366         unsigned int num;
3367         uint32 init_attr;
3368         uint32 trunc_attr;
3369         uint32 result_attr;
3370 };
3371
3372 static struct trunc_open_results attr_results[] = {
3373         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
3374         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
3375         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
3376         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
3377         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
3378         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
3379         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3380         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3381         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
3382         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3383         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3384         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
3385         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3386         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3387         { 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 },
3388         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3389         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3390         { 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 },
3391         { 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 },
3392         { 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 },
3393         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3394         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
3395         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
3396         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3397         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
3398         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
3399 };
3400
3401 static BOOL run_openattrtest(int dummy)
3402 {
3403         struct cli_state *cli1;
3404         const char *fname = "\\openattr.file";
3405         int fnum1;
3406         BOOL correct = True;
3407         uint16 attr;
3408         unsigned int i, j, k, l;
3409         int failures = 0;
3410
3411         printf("starting open attr test\n");
3412         
3413         if (!torture_open_connection(&cli1)) {
3414                 return False;
3415         }
3416         
3417         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
3418                 cli_setatr(cli1->tree, fname, 0, 0);
3419                 cli_unlink(cli1->tree, fname);
3420                 fnum1 = cli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_WRITE_DATA, open_attrs_table[i],
3421                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3422
3423                 if (fnum1 == -1) {
3424                         printf("open %d (1) of %s failed (%s)\n", i, fname, cli_errstr(cli1->tree));
3425                         return False;
3426                 }
3427
3428                 if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3429                         printf("close %d (1) of %s failed (%s)\n", i, fname, cli_errstr(cli1->tree));
3430                         return False;
3431                 }
3432
3433                 for (j = 0; j < ARRAY_SIZE(open_attrs_table); j++) {
3434                         fnum1 = cli_nt_create_full(cli1->tree, fname, 0, 
3435                                                    SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA, 
3436                                                    open_attrs_table[j],
3437                                                    NTCREATEX_SHARE_ACCESS_NONE, 
3438                                                    NTCREATEX_DISP_OVERWRITE, 0, 0);
3439
3440                         if (fnum1 == -1) {
3441                                 for (l = 0; l < ARRAY_SIZE(attr_results); l++) {
3442                                         if (attr_results[l].num == k) {
3443                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
3444                                                                 k, open_attrs_table[i],
3445                                                                 open_attrs_table[j],
3446                                                                 fname, NT_STATUS_V(cli_nt_error(cli1->tree)), cli_errstr(cli1->tree));
3447                                                 correct = False;
3448                                                 CHECK_MAX_FAILURES(error_exit);
3449                                         }
3450                                 }
3451                                 if (NT_STATUS_V(cli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) {
3452                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
3453                                                         k, open_attrs_table[i], open_attrs_table[j],
3454                                                         cli_errstr(cli1->tree));
3455                                         correct = False;
3456                                         CHECK_MAX_FAILURES(error_exit);
3457                                 }
3458 #if 0
3459                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
3460 #endif
3461                                 k++;
3462                                 continue;
3463                         }
3464
3465                         if (NT_STATUS_IS_ERR(cli_close(cli1->tree, fnum1))) {
3466                                 printf("close %d (2) of %s failed (%s)\n", j, fname, cli_errstr(cli1->tree));
3467                                 return False;
3468                         }
3469
3470                         if (NT_STATUS_IS_ERR(cli_getatr(cli1->tree, fname, &attr, NULL, NULL))) {
3471                                 printf("getatr(2) failed (%s)\n", cli_errstr(cli1->tree));
3472                                 return False;
3473                         }
3474
3475 #if 0
3476                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
3477                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
3478 #endif
3479
3480                         for (l = 0; l < ARRAY_SIZE(attr_results); l++) {
3481                                 if (attr_results[l].num == k) {
3482                                         if (attr != attr_results[l].result_attr ||
3483                                                         open_attrs_table[i] != attr_results[l].init_attr ||
3484                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
3485                                                 printf("[%d] getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
3486                                                         k, open_attrs_table[i],
3487                                                         open_attrs_table[j],
3488                                                         (unsigned int)attr,
3489                                                         attr_results[l].result_attr);
3490                                                 correct = False;
3491                                                 CHECK_MAX_FAILURES(error_exit);
3492                                         }
3493                                         break;
3494                                 }
3495                         }
3496                         k++;
3497                 }
3498         }
3499 error_exit:
3500         cli_setatr(cli1->tree, fname, 0, 0);
3501         cli_unlink(cli1->tree, fname);
3502
3503         printf("open attr test %s.\n", correct ? "passed" : "failed");
3504
3505         if (!torture_close_connection(cli1)) {
3506                 correct = False;
3507         }
3508         return correct;
3509 }
3510
3511 static void list_fn(file_info *finfo, const char *name, void *state)
3512 {
3513         
3514 }
3515
3516 /*
3517   test directory listing speed
3518  */
3519 static BOOL run_dirtest(int dummy)
3520 {
3521         int i;
3522         struct cli_state *cli;
3523         int fnum;
3524         double t1;
3525         BOOL correct = True;
3526
3527         printf("starting directory test\n");
3528
3529         if (!torture_open_connection(&cli)) {
3530                 return False;
3531         }
3532
3533         printf("Creating %d random filenames\n", torture_numops);
3534
3535         srandom(0);
3536         for (i=0;i<torture_numops;i++) {
3537                 char *fname;
3538                 asprintf(&fname, "\\%x", (int)random());
3539                 fnum = cli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
3540                 if (fnum == -1) {
3541                         fprintf(stderr,"Failed to open %s\n", fname);
3542                         return False;
3543                 }
3544                 cli_close(cli->tree, fnum);
3545                 free(fname);
3546         }
3547
3548         t1 = end_timer();
3549
3550         printf("Matched %d\n", cli_list(cli->tree, "a*.*", 0, list_fn, NULL));
3551         printf("Matched %d\n", cli_list(cli->tree, "b*.*", 0, list_fn, NULL));
3552         printf("Matched %d\n", cli_list(cli->tree, "xyzabc", 0, list_fn, NULL));
3553
3554         printf("dirtest core %g seconds\n", end_timer() - t1);
3555
3556         srandom(0);
3557         for (i=0;i<torture_numops;i++) {
3558                 char *fname;
3559                 asprintf(&fname, "\\%x", (int)random());
3560                 cli_unlink(cli->tree, fname);
3561                 free(fname);
3562         }
3563
3564         if (!torture_close_connection(cli)) {
3565                 correct = False;
3566         }
3567
3568         printf("finished dirtest\n");
3569
3570         return correct;
3571 }
3572
3573 static void del_fn(file_info *finfo, const char *mask, void *state)
3574 {
3575         struct cli_state *pcli = (struct cli_state *)state;
3576         char *fname;
3577         asprintf(&fname, "\\LISTDIR\\%s", finfo->name);
3578
3579         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
3580                 return;
3581
3582         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
3583                 if (NT_STATUS_IS_ERR(cli_rmdir(pcli->tree, fname)))
3584                         printf("del_fn: failed to rmdir %s, error=%s\n", fname, cli_errstr(pcli->tree) );
3585         } else {
3586                 if (NT_STATUS_IS_ERR(cli_unlink(pcli->tree, fname)))
3587                         printf("del_fn: failed to unlink %s, error=%s\n", fname, cli_errstr(pcli->tree) );
3588         }
3589         free(fname);
3590 }
3591
3592
3593 /*
3594   sees what IOCTLs are supported
3595  */
3596 BOOL torture_ioctl_test(int dummy)
3597 {
3598         struct cli_state *cli;
3599         uint16 device, function;
3600         int fnum;
3601         const char *fname = "\\ioctl.dat";
3602         NTSTATUS status;
3603         union smb_ioctl parms;
3604         TALLOC_CTX *mem_ctx;
3605
3606         if (!torture_open_connection(&cli)) {
3607                 return False;
3608         }
3609
3610         mem_ctx = talloc_init("ioctl_test");
3611
3612         printf("starting ioctl test\n");
3613
3614         cli_unlink(cli->tree, fname);
3615
3616         fnum = cli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
3617         if (fnum == -1) {
3618                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli->tree));
3619                 return False;
3620         }
3621
3622         parms.ioctl.level = RAW_IOCTL_IOCTL;
3623         parms.ioctl.in.request = IOCTL_QUERY_JOB_INFO;
3624         status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
3625         printf("ioctl job info: %s\n", cli_errstr(cli->tree));
3626
3627         for (device=0;device<0x100;device++) {
3628                 printf("testing device=0x%x\n", device);
3629                 for (function=0;function<0x100;function++) {
3630                         parms.ioctl.in.request = (device << 16) | function;
3631                         status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
3632
3633                         if (NT_STATUS_IS_OK(status)) {
3634                                 printf("ioctl device=0x%x function=0x%x OK : %d bytes\n", 
3635                                         device, function, parms.ioctl.out.blob.length);
3636                         }
3637                 }
3638         }
3639
3640         if (!torture_close_connection(cli)) {
3641                 return False;
3642         }
3643
3644         return True;
3645 }
3646
3647
3648 /*
3649   tries variants of chkpath
3650  */
3651 BOOL torture_chkpath_test(int dummy)
3652 {
3653         struct cli_state *cli;
3654         int fnum;
3655         BOOL ret;
3656
3657         if (!torture_open_connection(&cli)) {
3658                 return False;
3659         }
3660
3661         printf("starting chkpath test\n");
3662
3663         printf("Testing valid and invalid paths\n");
3664
3665         /* cleanup from an old run */
3666         cli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
3667         cli_unlink(cli->tree, "\\chkpath.dir\\*");
3668         cli_rmdir(cli->tree, "\\chkpath.dir");
3669
3670         if (NT_STATUS_IS_ERR(cli_mkdir(cli->tree, "\\chkpath.dir"))) {
3671                 printf("mkdir1 failed : %s\n", cli_errstr(cli->tree));
3672                 return False;
3673         }
3674
3675         if (NT_STATUS_IS_ERR(cli_mkdir(cli->tree, "\\chkpath.dir\\dir2"))) {
3676                 printf("mkdir2 failed : %s\n", cli_errstr(cli->tree));
3677                 return False;
3678         }
3679
3680         fnum = cli_open(cli->tree, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
3681         if (fnum == -1) {
3682                 printf("open1 failed (%s)\n", cli_errstr(cli->tree));
3683                 return False;
3684         }
3685         cli_close(cli->tree, fnum);
3686
3687         if (NT_STATUS_IS_ERR(cli_chkpath(cli->tree, "\\chkpath.dir"))) {
3688                 printf("chkpath1 failed: %s\n", cli_errstr(cli->tree));
3689                 ret = False;
3690         }
3691
3692         if (NT_STATUS_IS_ERR(cli_chkpath(cli->tree, "\\chkpath.dir\\dir2"))) {
3693                 printf("chkpath2 failed: %s\n", cli_errstr(cli->tree));
3694                 ret = False;
3695         }
3696
3697         if (NT_STATUS_IS_ERR(cli_chkpath(cli->tree, "\\chkpath.dir\\foo.txt"))) {
3698                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath, 
3699                                   NT_STATUS_NOT_A_DIRECTORY);
3700         } else {
3701                 printf("* chkpath on a file should fail\n");
3702                 ret = False;
3703         }
3704
3705         if (NT_STATUS_IS_ERR(cli_chkpath(cli->tree, "\\chkpath.dir\\bar.txt"))) {
3706                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadfile, 
3707                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
3708         } else {
3709                 printf("* chkpath on a non existent file should fail\n");
3710                 ret = False;
3711         }
3712
3713         if (NT_STATUS_IS_ERR(cli_chkpath(cli->tree, "\\chkpath.dir\\dirxx\\bar.txt"))) {
3714                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath, 
3715                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
3716         } else {
3717                 printf("* chkpath on a non existent component should fail\n");
3718                 ret = False;
3719         }
3720
3721         cli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
3722         cli_unlink(cli->tree, "\\chkpath.dir\\*");
3723         cli_rmdir(cli->tree, "\\chkpath.dir");
3724
3725         if (!torture_close_connection(cli)) {
3726                 return False;
3727         }
3728
3729         return ret;
3730 }
3731
3732 static BOOL run_dirtest1(int dummy)
3733 {
3734         int i;
3735         struct cli_state *cli;
3736         int fnum, num_seen;
3737         BOOL correct = True;
3738
3739         printf("starting directory test\n");
3740
3741         if (!torture_open_connection(&cli)) {
3742                 return False;
3743         }
3744
3745         cli_list(cli->tree, "\\LISTDIR\\*", 0, del_fn, cli);
3746         cli_list(cli->tree, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
3747         if (cli_deltree(cli->tree, "\\LISTDIR") == -1) {
3748                 fprintf(stderr,"Failed to deltree %s, error=%s\n", "\\LISTDIR", cli_errstr(cli->tree));
3749                 return False;
3750         }
3751         if (NT_STATUS_IS_ERR(cli_mkdir(cli->tree, "\\LISTDIR"))) {
3752                 fprintf(stderr,"Failed to mkdir %s, error=%s\n", "\\LISTDIR", cli_errstr(cli->tree));
3753                 return False;
3754         }
3755
3756         printf("Creating %d files\n", torture_entries);
3757
3758         /* Create torture_entries files and torture_entries directories. */
3759         for (i=0;i<torture_entries;i++) {
3760                 char *fname;
3761                 asprintf(&fname, "\\LISTDIR\\f%d", i);
3762                 fnum = cli_nt_create_full(cli->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
3763                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
3764                 if (fnum == -1) {
3765                         fprintf(stderr,"Failed to open %s, error=%s\n", fname, cli_errstr(cli->tree));
3766                         return False;
3767                 }
3768                 free(fname);
3769                 cli_close(cli->tree, fnum);
3770         }
3771         for (i=0;i<torture_entries;i++) {
3772                 char *fname;
3773                 asprintf(&fname, "\\LISTDIR\\d%d", i);
3774                 if (NT_STATUS_IS_ERR(cli_mkdir(cli->tree, fname))) {
3775                         fprintf(stderr,"Failed to open %s, error=%s\n", fname, cli_errstr(cli->tree));
3776                         return False;
3777                 }
3778                 free(fname);
3779         }
3780
3781         /* Now ensure that doing an old list sees both files and directories. */
3782         num_seen = cli_list_old(cli->tree, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, NULL);
3783         printf("num_seen = %d\n", num_seen );
3784         /* We should see (torture_entries) each of files & directories + . and .. */
3785         if (num_seen != (2*torture_entries)+2) {
3786                 correct = False;
3787                 fprintf(stderr,"entry count mismatch, should be %d, was %d\n",
3788                         (2*torture_entries)+2, num_seen);
3789         }
3790                 
3791
3792         /* Ensure if we have the "must have" bits we only see the
3793          * relevant entries.
3794          */
3795         num_seen = cli_list_old(cli->tree, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, NULL);
3796         printf("num_seen = %d\n", num_seen );
3797         if (num_seen != torture_entries+2) {
3798                 correct = False;
3799                 fprintf(stderr,"entry count mismatch, should be %d, was %d\n",
3800                         torture_entries+2, num_seen);
3801         }
3802
3803         num_seen = cli_list_old(cli->tree, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, NULL);
3804         printf("num_seen = %d\n", num_seen );
3805         if (num_seen != torture_entries) {
3806                 correct = False;
3807                 fprintf(stderr,"entry count mismatch, should be %d, was %d\n",
3808                         torture_entries, num_seen);
3809         }
3810
3811         /* Delete everything. */
3812         cli_list(cli->tree, "\\LISTDIR\\*", 0, del_fn, cli);
3813         cli_list(cli->tree, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
3814         cli_rmdir(cli->tree, "\\LISTDIR");
3815
3816 #if 0
3817         printf("Matched %d\n", cli_list(cli->tree, "a*.*", 0, list_fn, NULL));
3818         printf("Matched %d\n", cli_list(cli->tree, "b*.*", 0, list_fn, NULL));
3819         printf("Matched %d\n", cli_list(cli->tree, "xyzabc", 0, list_fn, NULL));
3820 #endif
3821
3822         if (!torture_close_connection(cli)) {
3823                 correct = False;
3824         }
3825
3826         printf("finished dirtest1\n");
3827
3828         return correct;
3829 }
3830
3831
3832 /*
3833    simple test harness for playing with deny modes
3834  */
3835 static BOOL run_deny3test(int dummy)
3836 {
3837         struct cli_state *cli1, *cli2;
3838         int fnum1, fnum2;
3839         const char *fname;
3840
3841         printf("starting deny3 test\n");
3842
3843         printf("Testing simple deny modes\n");
3844         
3845         if (!torture_open_connection(&cli1)) {
3846                 return False;
3847         }
3848         if (!torture_open_connection(&cli2)) {
3849                 return False;
3850         }
3851
3852         fname = "\\deny_dos1.dat";
3853
3854         cli_unlink(cli1->tree, fname);
3855         fnum1 = cli_open(cli1->tree, fname, O_CREAT|O_TRUNC|O_WRONLY, DENY_DOS);
3856         fnum2 = cli_open(cli1->tree, fname, O_CREAT|O_TRUNC|O_WRONLY, DENY_DOS);
3857         if (fnum1 != -1) cli_close(cli1->tree, fnum1);
3858         if (fnum2 != -1) cli_close(cli1->tree, fnum2);
3859         cli_unlink(cli1->tree, fname);
3860         printf("fnum1=%d fnum2=%d\n", fnum1, fnum2);
3861
3862
3863         fname = "\\deny_dos2.dat";
3864
3865         cli_unlink(cli1->tree, fname);
3866         fnum1 = cli_open(cli1->tree, fname, O_CREAT|O_TRUNC|O_WRONLY, DENY_DOS);
3867         fnum2 = cli_open(cli2->tree, fname, O_CREAT|O_TRUNC|O_WRONLY, DENY_DOS);
3868         if (fnum1 != -1) cli_close(cli1->tree, fnum1);
3869         if (fnum2 != -1) cli_close(cli2->tree, fnum2);
3870         cli_unlink(cli1->tree, fname);
3871         printf("fnum1=%d fnum2=%d\n", fnum1, fnum2);
3872
3873
3874         torture_close_connection(cli1);
3875         torture_close_connection(cli2);
3876
3877         return True;
3878 }
3879
3880 /*
3881   parse a //server/share type UNC name
3882 */
3883 static BOOL parse_unc(const char *unc_name, char **hostname, char **sharename)
3884 {
3885         char *p;
3886
3887         if (strncmp(unc_name, "//", 2)) {
3888                 return False;
3889         }
3890
3891         *hostname = strdup(&unc_name[2]);
3892         p = strchr_m(&(*hostname)[2],'/');
3893         if (!p) {
3894                 return False;
3895         }
3896         *p = 0;
3897         *sharename = strdup(p+1);
3898
3899         return True;
3900 }
3901
3902
3903
3904 static void sigcont(void)
3905 {
3906 }
3907
3908 double torture_create_procs(BOOL (*fn)(struct cli_state *, int), BOOL *result)
3909 {
3910         int i, status;
3911         volatile pid_t *child_status;
3912         volatile BOOL *child_status_out;
3913         int synccount;
3914         int tries = 8;
3915         double start_time_limit = 10 + (torture_nprocs * 1.5);
3916         char **unc_list = NULL;
3917         char *p;
3918         int num_unc_names = 0;
3919
3920         synccount = 0;
3921
3922         signal(SIGCONT, sigcont);
3923
3924         child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*torture_nprocs);
3925         if (!child_status) {
3926                 printf("Failed to setup shared memory\n");
3927                 return -1;
3928         }
3929
3930         child_status_out = (volatile BOOL *)shm_setup(sizeof(BOOL)*torture_nprocs);
3931         if (!child_status_out) {
3932                 printf("Failed to setup result status shared memory\n");
3933                 return -1;
3934         }
3935
3936         p = lp_parm_string(-1, "torture", "unclist");
3937         if (p) {
3938                 unc_list = file_lines_load(p, &num_unc_names);
3939                 if (!unc_list || num_unc_names <= 0) {
3940                         printf("Failed to load unc names list from %s\n", p);
3941                         exit(1);
3942                 }
3943         }
3944
3945         for (i = 0; i < torture_nprocs; i++) {
3946                 child_status[i] = 0;
3947                 child_status_out[i] = True;
3948         }
3949
3950         start_timer();
3951
3952         for (i=0;i<torture_nprocs;i++) {
3953                 procnum = i;
3954                 if (fork() == 0) {
3955                         char *myname;
3956                         char *hostname=NULL, *sharename;
3957
3958                         pid_t mypid = getpid();
3959                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
3960
3961                         asprintf(&myname, "CLIENT%d", i);
3962                         lp_set_cmdline("netbios name", myname);
3963                         free(myname);
3964
3965
3966                         if (unc_list) {
3967                                 if (!parse_unc(unc_list[i % num_unc_names],
3968                                                &hostname, &sharename)) {
3969                                         printf("Failed to parse UNC name %s\n",
3970                                                unc_list[i % num_unc_names]);
3971                                         exit(1);
3972                                 }
3973                         }
3974
3975                         while (1) {
3976                                 if (hostname) {
3977                                         if (torture_open_connection_share(&current_cli,
3978                                                                           hostname, 
3979                                                                           sharename)) {
3980                                                 break;
3981                                         }
3982                                 } else if (torture_open_connection(&current_cli)) {
3983                                                 break;
3984                                 }
3985                                 if (tries-- == 0) {
3986                                         printf("pid %d failed to start\n", (int)getpid());
3987                                         _exit(1);
3988                                 }
3989                                 msleep(100);    
3990                         }
3991
3992                         child_status[i] = getpid();
3993
3994                         pause();
3995
3996                         if (child_status[i]) {
3997                                 printf("Child %d failed to start!\n", i);
3998                                 child_status_out[i] = 1;
3999                                 _exit(1);
4000                         }
4001
4002                         child_status_out[i] = fn(current_cli, i);
4003                         _exit(0);
4004                 }
4005         }
4006
4007         do {
4008                 synccount = 0;
4009                 for (i=0;i<torture_nprocs;i++) {
4010                         if (child_status[i]) synccount++;
4011                 }
4012                 if (synccount == torture_nprocs) break;
4013                 msleep(100);
4014         } while (end_timer() < start_time_limit);
4015
4016         if (synccount != torture_nprocs) {
4017                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
4018                 *result = False;
4019                 return end_timer();
4020         }
4021
4022         printf("Starting %d clients\n", torture_nprocs);
4023
4024         /* start the client load */
4025         start_timer();
4026         for (i=0;i<torture_nprocs;i++) {
4027                 child_status[i] = 0;
4028         }
4029         kill(0, SIGCONT);
4030
4031         printf("%d clients started\n", torture_nprocs);
4032
4033         for (i=0;i<torture_nprocs;i++) {
4034                 int ret;
4035                 while ((ret=waitpid(0, &status, 0)) == -1 && errno == EINTR) /* noop */ ;
4036                 if (ret == -1 || WEXITSTATUS(status) != 0) {
4037                         *result = False;
4038                 }
4039         }
4040
4041         printf("\n");
4042         
4043         for (i=0;i<torture_nprocs;i++) {
4044                 if (!child_status_out[i]) {
4045                         *result = False;
4046                 }
4047         }
4048         return end_timer();
4049 }
4050
4051 #define FLAG_MULTIPROC 1
4052
4053 static struct {
4054         const char *name;
4055         BOOL (*fn)(int);
4056         unsigned flags;
4057 } torture_ops[] = {
4058         {"FDPASS", run_fdpasstest, 0},
4059         {"LOCK1",  run_locktest1,  0},
4060         {"LOCK2",  run_locktest2,  0},
4061         {"LOCK3",  run_locktest3,  0},
4062         {"LOCK4",  run_locktest4,  0},
4063         {"LOCK5",  run_locktest5,  0},
4064         {"LOCK6",  run_locktest6,  0},
4065         {"LOCK7",  run_locktest7,  0},
4066         {"UNLINK", run_unlinktest, 0},
4067         {"ATTR",   run_attrtest,   0},
4068         {"TRANS2", run_trans2test, 0},
4069         {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
4070         {"TORTURE",run_torture,    FLAG_MULTIPROC},
4071         {"NEGNOWAIT", run_negprot_nowait, 0},
4072         {"NBENCH",  torture_nbench, 0},
4073         {"DIR",  run_dirtest, 0},
4074         {"DIR1",  run_dirtest1, 0},
4075         {"DENY1",  torture_denytest1, 0},
4076         {"DENY2",  torture_denytest2, 0},
4077         {"TCON",  run_tcon_test, 0},
4078         {"TCONDEV",  run_tcon_devtype_test, 0},
4079         {"VUID", run_vuidtest, 0},
4080 #if 0
4081         {"DFSBASIC", torture_dfs_basic, 0},
4082         {"DFSRENAME", torture_dfs_rename, 0},
4083         {"DFSRANDOM", torture_dfs_random, 0},
4084 #endif
4085         {"RW1",  run_readwritetest, 0},
4086         {"RW2",  run_readwritemulti, FLAG_MULTIPROC},
4087         {"OPEN", run_opentest, 0},
4088         {"DENY3", run_deny3test, 0},
4089 #if 1
4090         {"OPENATTR", run_openattrtest, 0},
4091 #endif
4092         {"XCOPY", run_xcopy, 0},
4093         {"RENAME", run_rename, 0},
4094         {"DELETE", run_deletetest, 0},
4095         {"PROPERTIES", run_properties, 0},
4096         {"MANGLE", torture_mangle, 0},
4097         {"UTABLE", torture_utable, 0},
4098         {"CASETABLE", torture_casetable, 0},
4099         {"CHARSET", torture_charset, 0},
4100         {"PIPE_NUMBER", run_pipe_number, 0},
4101         {"IOCTL",  torture_ioctl_test, 0},
4102         {"CHKPATH",  torture_chkpath_test, 0},
4103         {"HOLDCON",  torture_holdcon, 0},
4104         {"RAW-QFSINFO", torture_raw_qfsinfo, 0},
4105         {"RAW-QFILEINFO", torture_raw_qfileinfo, 0},
4106         {"RAW-SFILEINFO", torture_raw_sfileinfo, 0},
4107         {"RAW-SFILEINFO-BUG", torture_raw_sfileinfo_bug, 0},
4108         {"RAW-SEARCH", torture_raw_search, 0},
4109         {"RAW-CLOSE", torture_raw_close, 0},
4110         {"RAW-OPEN", torture_raw_open, 0},
4111         {"RAW-MKDIR", torture_raw_mkdir, 0},
4112         {"RAW-OPLOCK", torture_raw_oplock, 0},
4113         {"RAW-NOTIFY", torture_raw_notify, 0},
4114         {"RAW-MUX", torture_raw_mux, 0},
4115         {"RAW-IOCTL", torture_raw_ioctl, 0},
4116         {"RAW-CHKPATH", torture_raw_chkpath, 0},
4117         {"RAW-UNLINK", torture_raw_unlink, 0},
4118         {"RAW-READ", torture_raw_read, 0},
4119         {"RAW-WRITE", torture_raw_write, 0},
4120         {"RAW-LOCK", torture_raw_lock, 0},
4121         {"RAW-CONTEXT", torture_raw_context, 0},
4122         {"RAW-RENAME", torture_raw_rename, 0},
4123         {"RAW-SEEK", torture_raw_seek, 0},
4124         {"SCAN-TRANS2", torture_trans2_scan, 0},
4125         {"SCAN-NTTRANS", torture_nttrans_scan, 0},
4126         {"SCAN-ALIASES", torture_trans2_aliases, 0},
4127         {"SCAN-SMB", torture_smb_scan, 0},
4128         {"RPC-LSA", torture_rpc_lsa, 0},
4129         {"RPC-ECHO", torture_rpc_echo, 0},
4130         {"RPC-DFS", torture_rpc_dfs, 0},
4131         {"RPC-SPOOLSS", torture_rpc_spoolss, 0},
4132         {"RPC-SAMR", torture_rpc_samr, 0},
4133         {"RPC-NETLOGON", torture_rpc_netlogon, 0},
4134         {"RPC-WKSSVC", torture_rpc_wkssvc, 0},
4135         {"RPC-SRVSVC", torture_rpc_srvsvc, 0},
4136         {"RPC-ATSVC", torture_rpc_atsvc, 0},
4137         {"RPC-EVENTLOG", torture_rpc_eventlog, 0},
4138         {"RPC-EPMAPPER", torture_rpc_epmapper, 0},
4139         {"RPC-WINREG", torture_rpc_winreg, 0},
4140         {"RPC-MGMT", torture_rpc_mgmt, 0},
4141         {"RPC-SCANNER", torture_rpc_scanner, 0},
4142         {"RPC-AUTOIDL", torture_rpc_autoidl, 0},
4143         {NULL, NULL, 0}};
4144
4145
4146
4147 /****************************************************************************
4148 run a specified test or "ALL"
4149 ****************************************************************************/
4150 static BOOL run_test(const char *name)
4151 {
4152         BOOL ret = True;
4153         int i;
4154         BOOL matched = False;
4155
4156         if (strequal(name,"ALL")) {
4157                 for (i=0;torture_ops[i].name;i++) {
4158                         if (!run_test(torture_ops[i].name)) {
4159                                 ret = False;
4160                         }
4161                 }
4162                 return ret;
4163         }
4164
4165         for (i=0;torture_ops[i].name;i++) {
4166                 if (gen_fnmatch(name, torture_ops[i].name) == 0) {
4167                         double t;
4168                         matched = True;
4169                         printf("Running %s\n", torture_ops[i].name);
4170                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
4171                                 BOOL result;
4172                                 t = torture_create_procs(torture_ops[i].fn, &result);
4173                                 if (!result) { 
4174                                         ret = False;
4175                                         printf("TEST %s FAILED!\n", torture_ops[i].name);
4176                                 }
4177                                          
4178                         } else {
4179                                 start_timer();
4180                                 if (!torture_ops[i].fn(0)) {
4181                                         ret = False;
4182                                         printf("TEST %s FAILED!\n", torture_ops[i].name);
4183                                 }
4184                                 t = end_timer();
4185                         }
4186                         printf("%s took %g secs\n\n", torture_ops[i].name, t);
4187                 }
4188         }
4189
4190         if (!matched) {
4191                 printf("Unknown torture operation '%s'\n", name);
4192         }
4193
4194         return ret;
4195 }
4196
4197
4198 /*
4199   parse a username%password
4200 */
4201 static void parse_user(const char *user)
4202 {
4203         char *username, *password = NULL, *p;
4204
4205         username = strdup(user);
4206         p = strchr_m(username,'%');
4207         if (p) {
4208                 *p = 0;
4209                 password = strdup(p+1);
4210         }
4211
4212         lp_set_cmdline("torture:username", username);
4213
4214         if (password) {
4215                 lp_set_cmdline("torture:password", password);
4216         }
4217
4218         if (!lp_parm_string(-1,"torture","password")) {
4219                 password = getpass("password:");
4220
4221                 lp_set_cmdline("torture:password", password);
4222         }
4223 }
4224
4225 static void usage(void)
4226 {
4227         int i;
4228
4229         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
4230
4231         printf("\t-d debuglevel\n");
4232         printf("\t-U user%%pass\n");
4233         printf("\t-k use kerberos\n");
4234         printf("\t-N numprocs\n");
4235         printf("\t-n my_netbios_name\n");
4236         printf("\t-W workgroup\n");
4237         printf("\t-o num_operations\n");
4238         printf("\t-e num files(entries)\n");
4239         printf("\t-O socket_options\n");
4240         printf("\t-m maximum protocol\n");
4241         printf("\t-L use oplocks\n");
4242         printf("\t-c CLIENT.TXT   specify client load file for NBENCH\n");
4243         printf("\t-t timelimit    specify NBENCH time limit (seconds)\n");
4244         printf("\t-C filename     specifies file with list of UNCs for connections\n");
4245         printf("\t-A showall\n");
4246         printf("\t-p port\n");
4247         printf("\t-s seed\n");
4248         printf("\t-f max failures\n");
4249         printf("\t-b bypass I/O (NBENCH)\n");
4250         printf("\t-X enable dangerous tests\n");
4251         printf("\n\n");
4252
4253         printf("tests are:");
4254         for (i=0;torture_ops[i].name;i++) {
4255                 printf(" %s", torture_ops[i].name);
4256         }
4257         printf("\n");
4258
4259         printf("default test is ALL\n");
4260         
4261         exit(1);
4262 }
4263
4264 /****************************************************************************
4265   main program
4266 ****************************************************************************/
4267  int main(int argc,char *argv[])
4268 {
4269         int opt, i;
4270         char *p;
4271         BOOL correct = True;
4272         char *host, *share, *username;
4273
4274         setup_logging("smbtorture", DEBUG_STDOUT);
4275
4276 #ifdef HAVE_SETBUFFER
4277         setbuffer(stdout, NULL, 0);
4278 #endif
4279
4280         lp_load(dyn_CONFIGFILE,True,False,False);
4281         load_interfaces();
4282
4283         if (argc < 2) {
4284                 usage();
4285         }
4286
4287         for(p = argv[1]; *p; p++)
4288           if(*p == '\\')
4289             *p = '/';
4290
4291
4292         /* see if its a RPC transport specifier */
4293         if (strncmp(argv[1], "ncacn_", 6) == 0) {
4294                 lp_set_cmdline("torture:binding", argv[1]);
4295         } else {
4296                 char *binding = NULL;
4297
4298                 if (!parse_unc(argv[1], &host, &share)) {
4299                         usage();
4300                 }
4301
4302                 lp_set_cmdline("torture:host", host);
4303                 lp_set_cmdline("torture:share", share);
4304                 lp_set_cmdline("torture:password", "");
4305                 asprintf(&binding, "ncacn_np:%s", host);
4306                 lp_set_cmdline("torture:binding", binding);
4307         }
4308
4309         if (getenv("LOGNAME")) {
4310                 username = strdup(getenv("LOGNAME"));
4311         }
4312         lp_set_cmdline("torture:username", username);
4313
4314
4315         argc--;
4316         argv++;
4317
4318         srandom(time(NULL));
4319
4320         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:e:m:Ld:Ac:ks:f:s:t:C:X")) != EOF) {
4321                 switch (opt) {
4322                 case 'p':
4323                         lp_set_cmdline("smb ports", optarg);
4324                         break;
4325                 case 'W':
4326                         lp_set_cmdline("workgroup", optarg);
4327                         break;
4328                 case 'm':
4329                         lp_set_cmdline("protocol", optarg);
4330                         break;
4331                 case 'n':
4332                         lp_set_cmdline("netbios name", optarg);
4333                         break;
4334                 case 'd':
4335                         lp_set_cmdline("debug level", optarg);
4336                         setup_logging(NULL, DEBUG_STDOUT);
4337                         break;
4338                 case 'O':
4339                         lp_set_cmdline("socket options", optarg);
4340                         break;
4341                 case 's':
4342                         srandom(atoi(optarg));
4343                         break;
4344                 case 'N':
4345                         torture_nprocs = atoi(optarg);
4346                         break;
4347                 case 'o':
4348                         torture_numops = atoi(optarg);
4349                         break;
4350                 case 'e':
4351                         torture_entries = atoi(optarg);
4352                         break;
4353                 case 'L':
4354                         use_oplocks = True;
4355                         break;
4356                 case 'A':
4357                         torture_showall = True;
4358                         break;
4359                 case 'c':
4360                         lp_set_cmdline("torture:loadfile", optarg);
4361                         break;
4362                 case 'C':
4363                         lp_set_cmdline("torture:unclist", optarg);
4364                         break;
4365                 case 't':
4366                         lp_set_cmdline("torture:timelimit", optarg);
4367                         break;
4368                 case 'k':
4369 #ifdef HAVE_KRB5
4370                         use_kerberos = True;
4371 #else
4372                         d_printf("No kerberos support compiled in\n");
4373                         exit(1);
4374 #endif
4375                         break;
4376                 case 'U':
4377                         parse_user(optarg);
4378                         break;
4379                 case 'f':
4380                         torture_failures = atoi(optarg);
4381                         break;
4382
4383                 case 'X':
4384                         lp_set_cmdline("torture:dangerous", "1");
4385                         break;
4386
4387                 default:
4388                         printf("Unknown option %c (%d)\n", (char)opt, opt);
4389                         usage();
4390                 }
4391         }
4392
4393         if (!lp_parm_string(-1,"torture","password")) {
4394                 lp_set_cmdline("torture:password", "");
4395         }
4396
4397         if (argc == optind) {
4398                 printf("You must specify a test to run, or 'ALL'\n");
4399         } else {
4400                 for (i=optind;i<argc;i++) {
4401                         if (!run_test(argv[i])) {
4402                                 correct = False;
4403                         }
4404                 }
4405         }
4406
4407         if (correct) {
4408                 return(0);
4409         } else {
4410                 return(1);
4411         }
4412 }