s3-lib Replace StrCaseCmp() with strcasecmp_m()
[obnox/samba/samba-obnox.git] / source3 / torture / torture.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-1998
5    Copyright (C) Jeremy Allison 2009
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/shmem.h"
23 #include "wbc_async.h"
24 #include "torture/proto.h"
25 #include "libcli/security/security.h"
26 #include "tldap.h"
27 #include "tldap_util.h"
28 #include "../librpc/gen_ndr/svcctl.h"
29 #include "memcache.h"
30 #include "nsswitch/winbind_client.h"
31 #include "dbwrap.h"
32 #include "talloc_dict.h"
33 #include "async_smb.h"
34 #include "libsmb/libsmb.h"
35 #include "libsmb/clirap.h"
36 #include "trans2.h"
37 #include "libsmb/nmblib.h"
38 #include "../lib/util/tevent_ntstatus.h"
39 #include "util_tdb.h"
40
41 extern char *optarg;
42 extern int optind;
43
44 static fstring host, workgroup, share, password, username, myname;
45 static int max_protocol = PROTOCOL_NT1;
46 static const char *sockops="TCP_NODELAY";
47 static int nprocs=1;
48 static int port_to_use=0;
49 int torture_numops=100;
50 int torture_blocksize=1024*1024;
51 static int procnum; /* records process count number when forking */
52 static struct cli_state *current_cli;
53 static fstring randomfname;
54 static bool use_oplocks;
55 static bool use_level_II_oplocks;
56 static const char *client_txt = "client_oplocks.txt";
57 static bool use_kerberos;
58 static fstring multishare_conn_fname;
59 static bool use_multishare_conn = False;
60 static bool do_encrypt;
61 static const char *local_path = NULL;
62 static int signing_state = Undefined;
63 char *test_filename;
64
65 bool torture_showall = False;
66
67 static double create_procs(bool (*fn)(int), bool *result);
68
69
70 /* return a pointer to a anonymous shared memory segment of size "size"
71    which will persist across fork() but will disappear when all processes
72    exit 
73
74    The memory is not zeroed 
75
76    This function uses system5 shared memory. It takes advantage of a property
77    that the memory is not destroyed if it is attached when the id is removed
78    */
79 void *shm_setup(int size)
80 {
81         int shmid;
82         void *ret;
83
84 #ifdef __QNXNTO__
85         shmid = shm_open("private", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
86         if (shmid == -1) {
87                 printf("can't get shared memory\n");
88                 exit(1);
89         }
90         shm_unlink("private");
91         if (ftruncate(shmid, size) == -1) {
92                 printf("can't set shared memory size\n");
93                 exit(1);
94         }
95         ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0);
96         if (ret == MAP_FAILED) {
97                 printf("can't map shared memory\n");
98                 exit(1);
99         }
100 #else
101         shmid = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);
102         if (shmid == -1) {
103                 printf("can't get shared memory\n");
104                 exit(1);
105         }
106         ret = (void *)shmat(shmid, 0, 0);
107         if (!ret || ret == (void *)-1) {
108                 printf("can't attach to shared memory\n");
109                 return NULL;
110         }
111         /* the following releases the ipc, but note that this process
112            and all its children will still have access to the memory, its
113            just that the shmid is no longer valid for other shm calls. This
114            means we don't leave behind lots of shm segments after we exit 
115
116            See Stevens "advanced programming in unix env" for details
117            */
118         shmctl(shmid, IPC_RMID, 0);
119 #endif
120
121         return ret;
122 }
123
124 /********************************************************************
125  Ensure a connection is encrypted.
126 ********************************************************************/
127
128 static bool force_cli_encryption(struct cli_state *c,
129                         const char *sharename)
130 {
131         uint16 major, minor;
132         uint32 caplow, caphigh;
133         NTSTATUS status;
134
135         if (!SERVER_HAS_UNIX_CIFS(c)) {
136                 d_printf("Encryption required and "
137                         "server that doesn't support "
138                         "UNIX extensions - failing connect\n");
139                         return false;
140         }
141
142         status = cli_unix_extensions_version(c, &major, &minor, &caplow,
143                                              &caphigh);
144         if (!NT_STATUS_IS_OK(status)) {
145                 d_printf("Encryption required and "
146                         "can't get UNIX CIFS extensions "
147                         "version from server: %s\n", nt_errstr(status));
148                 return false;
149         }
150
151         if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
152                 d_printf("Encryption required and "
153                         "share %s doesn't support "
154                         "encryption.\n", sharename);
155                 return false;
156         }
157
158         if (c->use_kerberos) {
159                 status = cli_gss_smb_encryption_start(c);
160         } else {
161                 status = cli_raw_ntlm_smb_encryption_start(c,
162                                                 username,
163                                                 password,
164                                                 workgroup);
165         }
166
167         if (!NT_STATUS_IS_OK(status)) {
168                 d_printf("Encryption required and "
169                         "setup failed with error %s.\n",
170                         nt_errstr(status));
171                 return false;
172         }
173
174         return true;
175 }
176
177
178 static struct cli_state *open_nbt_connection(void)
179 {
180         struct nmb_name called, calling;
181         struct sockaddr_storage ss;
182         struct cli_state *c;
183         NTSTATUS status;
184
185         make_nmb_name(&calling, myname, 0x0);
186         make_nmb_name(&called , host, 0x20);
187
188         zero_sockaddr(&ss);
189
190         if (!(c = cli_initialise_ex(signing_state))) {
191                 printf("Failed initialize cli_struct to connect with %s\n", host);
192                 return NULL;
193         }
194
195         c->port = port_to_use;
196
197         status = cli_connect(c, host, &ss);
198         if (!NT_STATUS_IS_OK(status)) {
199                 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
200                 return NULL;
201         }
202
203         c->use_kerberos = use_kerberos;
204
205         c->timeout = 120000; /* set a really long timeout (2 minutes) */
206         if (use_oplocks) c->use_oplocks = True;
207         if (use_level_II_oplocks) c->use_level_II_oplocks = True;
208
209         if (!cli_session_request(c, &calling, &called)) {
210                 /*
211                  * Well, that failed, try *SMBSERVER ...
212                  * However, we must reconnect as well ...
213                  */
214                 status = cli_connect(c, host, &ss);
215                 if (!NT_STATUS_IS_OK(status)) {
216                         printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
217                         return NULL;
218                 }
219
220                 make_nmb_name(&called, "*SMBSERVER", 0x20);
221                 if (!cli_session_request(c, &calling, &called)) {
222                         printf("%s rejected the session\n",host);
223                         printf("We tried with a called name of %s & %s\n",
224                                 host, "*SMBSERVER");
225                         cli_shutdown(c);
226                         return NULL;
227                 }
228         }
229
230         return c;
231 }
232
233 /****************************************************************************
234  Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
235 ****************************************************************************/
236
237 static bool cli_bad_session_request(struct cli_state *cli,
238                          struct nmb_name *calling, struct nmb_name *called)
239 {
240         char *p;
241         int len = 4;
242         int namelen = 0;
243         char *tmp;
244
245         memcpy(&(cli->calling), calling, sizeof(*calling));
246         memcpy(&(cli->called ), called , sizeof(*called ));
247
248         /* put in the destination name */
249
250         tmp = name_mangle(talloc_tos(), cli->called.name,
251                           cli->called.name_type);
252         if (tmp == NULL) {
253                 return false;
254         }
255
256         p = cli->outbuf+len;
257         namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
258         if (namelen > 0) {
259                 memcpy(p, tmp, namelen);
260                 len += namelen;
261         }
262         TALLOC_FREE(tmp);
263
264         /* Deliberately corrupt the name len (first byte) */
265         *p = 100;
266
267         /* and my name */
268
269         tmp = name_mangle(talloc_tos(), cli->calling.name,
270                           cli->calling.name_type);
271         if (tmp == NULL) {
272                 return false;
273         }
274
275         p = cli->outbuf+len;
276         namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
277         if (namelen > 0) {
278                 memcpy(p, tmp, namelen);
279                 len += namelen;
280         }
281         TALLOC_FREE(tmp);
282         /* Deliberately corrupt the name len (first byte) */
283         *p = 100;
284
285         /* send a session request (RFC 1002) */
286         /* setup the packet length
287          * Remove four bytes from the length count, since the length
288          * field in the NBT Session Service header counts the number
289          * of bytes which follow.  The cli_send_smb() function knows
290          * about this and accounts for those four bytes.
291          * CRH.
292          */
293         len -= 4;
294         _smb_setlen(cli->outbuf,len);
295         SCVAL(cli->outbuf,0,0x81);
296
297         cli_send_smb(cli);
298         DEBUG(5,("Sent session request\n"));
299
300         if (!cli_receive_smb(cli))
301                 return False;
302
303         if (CVAL(cli->inbuf,0) != 0x82) {
304                 /* This is the wrong place to put the error... JRA. */
305                 cli->rap_error = CVAL(cli->inbuf,4);
306                 return False;
307         }
308         return(True);
309 }
310
311 static struct cli_state *open_bad_nbt_connection(void)
312 {
313         struct nmb_name called, calling;
314         struct sockaddr_storage ss;
315         struct cli_state *c;
316         NTSTATUS status;
317
318         make_nmb_name(&calling, myname, 0x0);
319         make_nmb_name(&called , host, 0x20);
320
321         zero_sockaddr(&ss);
322
323         if (!(c = cli_initialise_ex(signing_state))) {
324                 printf("Failed initialize cli_struct to connect with %s\n", host);
325                 return NULL;
326         }
327
328         c->port = 139;
329
330         status = cli_connect(c, host, &ss);
331         if (!NT_STATUS_IS_OK(status)) {
332                 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
333                 return NULL;
334         }
335
336         c->timeout = 4000; /* set a short timeout (4 seconds) */
337
338         if (!cli_bad_session_request(c, &calling, &called)) {
339                 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
340                 return NULL;
341         }
342
343         return c;
344 }
345
346
347 /* Insert a NULL at the first separator of the given path and return a pointer
348  * to the remainder of the string.
349  */
350 static char *
351 terminate_path_at_separator(char * path)
352 {
353         char * p;
354
355         if (!path) {
356                 return NULL;
357         }
358
359         if ((p = strchr_m(path, '/'))) {
360                 *p = '\0';
361                 return p + 1;
362         }
363
364         if ((p = strchr_m(path, '\\'))) {
365                 *p = '\0';
366                 return p + 1;
367         }
368
369         /* No separator. */
370         return NULL;
371 }
372
373 /*
374   parse a //server/share type UNC name
375 */
376 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
377                       char **hostname, char **sharename)
378 {
379         char *p;
380
381         *hostname = *sharename = NULL;
382
383         if (strncmp(unc_name, "\\\\", 2) &&
384             strncmp(unc_name, "//", 2)) {
385                 return False;
386         }
387
388         *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
389         p = terminate_path_at_separator(*hostname);
390
391         if (p && *p) {
392                 *sharename = talloc_strdup(mem_ctx, p);
393                 terminate_path_at_separator(*sharename);
394         }
395
396         if (*hostname && *sharename) {
397                 return True;
398         }
399
400         TALLOC_FREE(*hostname);
401         TALLOC_FREE(*sharename);
402         return False;
403 }
404
405 static bool torture_open_connection_share(struct cli_state **c,
406                                    const char *hostname, 
407                                    const char *sharename)
408 {
409         int flags = 0;
410         NTSTATUS status;
411
412         if (use_kerberos)
413                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
414         if (use_oplocks)
415                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
416         if (use_level_II_oplocks)
417                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
418
419         status = cli_full_connection(c, myname,
420                                      hostname, NULL, port_to_use, 
421                                      sharename, "?????", 
422                                      username, workgroup, 
423                                      password, flags, signing_state);
424         if (!NT_STATUS_IS_OK(status)) {
425                 printf("failed to open share connection: //%s/%s port:%d - %s\n",
426                         hostname, sharename, port_to_use, nt_errstr(status));
427                 return False;
428         }
429
430         (*c)->timeout = 120000; /* set a really long timeout (2 minutes) */
431
432         if (do_encrypt) {
433                 return force_cli_encryption(*c,
434                                         sharename);
435         }
436         return True;
437 }
438
439 bool torture_open_connection(struct cli_state **c, int conn_index)
440 {
441         char **unc_list = NULL;
442         int num_unc_names = 0;
443         bool result;
444
445         if (use_multishare_conn==True) {
446                 char *h, *s;
447                 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
448                 if (!unc_list || num_unc_names <= 0) {
449                         printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
450                         exit(1);
451                 }
452
453                 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
454                                       NULL, &h, &s)) {
455                         printf("Failed to parse UNC name %s\n",
456                                unc_list[conn_index % num_unc_names]);
457                         TALLOC_FREE(unc_list);
458                         exit(1);
459                 }
460
461                 result = torture_open_connection_share(c, h, s);
462
463                 /* h, s were copied earlier */
464                 TALLOC_FREE(unc_list);
465                 return result;
466         }
467
468         return torture_open_connection_share(c, host, share);
469 }
470
471 bool torture_cli_session_setup2(struct cli_state *cli, uint16 *new_vuid)
472 {
473         uint16 old_vuid = cli->vuid;
474         fstring old_user_name;
475         size_t passlen = strlen(password);
476         NTSTATUS status;
477         bool ret;
478
479         fstrcpy(old_user_name, cli->user_name);
480         cli->vuid = 0;
481         ret = NT_STATUS_IS_OK(cli_session_setup(cli, username,
482                                                 password, passlen,
483                                                 password, passlen,
484                                                 workgroup));
485         *new_vuid = cli->vuid;
486         cli->vuid = old_vuid;
487         status = cli_set_username(cli, old_user_name);
488         if (!NT_STATUS_IS_OK(status)) {
489                 return false;
490         }
491         return ret;
492 }
493
494
495 bool torture_close_connection(struct cli_state *c)
496 {
497         bool ret = True;
498         NTSTATUS status;
499
500         status = cli_tdis(c);
501         if (!NT_STATUS_IS_OK(status)) {
502                 printf("tdis failed (%s)\n", nt_errstr(status));
503                 ret = False;
504         }
505
506         cli_shutdown(c);
507
508         return ret;
509 }
510
511
512 /* check if the server produced the expected error code */
513 static bool check_error(int line, struct cli_state *c, 
514                         uint8 eclass, uint32 ecode, NTSTATUS nterr)
515 {
516         if (cli_is_dos_error(c)) {
517                 uint8 cclass;
518                 uint32 num;
519
520                 /* Check DOS error */
521
522                 cli_dos_error(c, &cclass, &num);
523
524                 if (eclass != cclass || ecode != num) {
525                         printf("unexpected error code class=%d code=%d\n", 
526                                (int)cclass, (int)num);
527                         printf(" expected %d/%d %s (line=%d)\n", 
528                                (int)eclass, (int)ecode, nt_errstr(nterr), line);
529                         return False;
530                 }
531
532         } else {
533                 NTSTATUS status;
534
535                 /* Check NT error */
536
537                 status = cli_nt_error(c);
538
539                 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
540                         printf("unexpected error code %s\n", nt_errstr(status));
541                         printf(" expected %s (line=%d)\n", nt_errstr(nterr), line);
542                         return False;
543                 }
544         }
545
546         return True;
547 }
548
549
550 static bool wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
551 {
552         while (!cli_lock(c, fnum, offset, len, -1, WRITE_LOCK)) {
553                 if (!check_error(__LINE__, c, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
554         }
555         return True;
556 }
557
558
559 static bool rw_torture(struct cli_state *c)
560 {
561         const char *lockfname = "\\torture.lck";
562         fstring fname;
563         uint16_t fnum;
564         uint16_t fnum2;
565         pid_t pid2, pid = getpid();
566         int i, j;
567         char buf[1024];
568         bool correct = True;
569         NTSTATUS status;
570
571         memset(buf, '\0', sizeof(buf));
572
573         status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
574                          DENY_NONE, &fnum2);
575         if (!NT_STATUS_IS_OK(status)) {
576                 status = cli_open(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
577         }
578         if (!NT_STATUS_IS_OK(status)) {
579                 printf("open of %s failed (%s)\n",
580                        lockfname, nt_errstr(status));
581                 return False;
582         }
583
584         for (i=0;i<torture_numops;i++) {
585                 unsigned n = (unsigned)sys_random()%10;
586
587                 if (i % 10 == 0) {
588                         printf("%d\r", i); fflush(stdout);
589                 }
590                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
591
592                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
593                         return False;
594                 }
595
596                 status = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC,
597                                   DENY_ALL, &fnum);
598                 if (!NT_STATUS_IS_OK(status)) {
599                         printf("open failed (%s)\n", nt_errstr(status));
600                         correct = False;
601                         break;
602                 }
603
604                 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
605                                       sizeof(pid), NULL);
606                 if (!NT_STATUS_IS_OK(status)) {
607                         printf("write failed (%s)\n", nt_errstr(status));
608                         correct = False;
609                 }
610
611                 for (j=0;j<50;j++) {
612                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
613                                               sizeof(pid)+(j*sizeof(buf)),
614                                               sizeof(buf), NULL);
615                         if (!NT_STATUS_IS_OK(status)) {
616                                 printf("write failed (%s)\n",
617                                        nt_errstr(status));
618                                 correct = False;
619                         }
620                 }
621
622                 pid2 = 0;
623
624                 if (cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
625                         printf("read failed (%s)\n", cli_errstr(c));
626                         correct = False;
627                 }
628
629                 if (pid2 != pid) {
630                         printf("data corruption!\n");
631                         correct = False;
632                 }
633
634                 status = cli_close(c, fnum);
635                 if (!NT_STATUS_IS_OK(status)) {
636                         printf("close failed (%s)\n", nt_errstr(status));
637                         correct = False;
638                 }
639
640                 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
641                 if (!NT_STATUS_IS_OK(status)) {
642                         printf("unlink failed (%s)\n", nt_errstr(status));
643                         correct = False;
644                 }
645
646                 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
647                 if (!NT_STATUS_IS_OK(status)) {
648                         printf("unlock failed (%s)\n", nt_errstr(status));
649                         correct = False;
650                 }
651         }
652
653         cli_close(c, fnum2);
654         cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
655
656         printf("%d\n", i);
657
658         return correct;
659 }
660
661 static bool run_torture(int dummy)
662 {
663         struct cli_state *cli;
664         bool ret;
665
666         cli = current_cli;
667
668         cli_sockopt(cli, sockops);
669
670         ret = rw_torture(cli);
671
672         if (!torture_close_connection(cli)) {
673                 ret = False;
674         }
675
676         return ret;
677 }
678
679 static bool rw_torture3(struct cli_state *c, char *lockfname)
680 {
681         uint16_t fnum = (uint16_t)-1;
682         unsigned int i = 0;
683         char buf[131072];
684         char buf_rd[131072];
685         unsigned count;
686         unsigned countprev = 0;
687         ssize_t sent = 0;
688         bool correct = True;
689         NTSTATUS status = NT_STATUS_OK;
690
691         srandom(1);
692         for (i = 0; i < sizeof(buf); i += sizeof(uint32))
693         {
694                 SIVAL(buf, i, sys_random());
695         }
696
697         if (procnum == 0)
698         {
699                 if (!NT_STATUS_IS_OK(cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN))) {
700                         printf("unlink failed (%s) (normal, this file should not exist)\n", cli_errstr(c));
701                 }
702
703                 status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
704                                   DENY_NONE, &fnum);
705                 if (!NT_STATUS_IS_OK(status)) {
706                         printf("first open read/write of %s failed (%s)\n",
707                                         lockfname, nt_errstr(status));
708                         return False;
709                 }
710         }
711         else
712         {
713                 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
714                 {
715                         status = cli_open(c, lockfname, O_RDONLY, 
716                                          DENY_NONE, &fnum);
717                         if (!NT_STATUS_IS_OK(status)) {
718                                 break;
719                         }
720                         smb_msleep(10);
721                 }
722                 if (!NT_STATUS_IS_OK(status)) {
723                         printf("second open read-only of %s failed (%s)\n",
724                                         lockfname, nt_errstr(status));
725                         return False;
726                 }
727         }
728
729         i = 0;
730         for (count = 0; count < sizeof(buf); count += sent)
731         {
732                 if (count >= countprev) {
733                         printf("%d %8d\r", i, count);
734                         fflush(stdout);
735                         i++;
736                         countprev += (sizeof(buf) / 20);
737                 }
738
739                 if (procnum == 0)
740                 {
741                         sent = ((unsigned)sys_random()%(20))+ 1;
742                         if (sent > sizeof(buf) - count)
743                         {
744                                 sent = sizeof(buf) - count;
745                         }
746
747                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
748                                               count, (size_t)sent, NULL);
749                         if (!NT_STATUS_IS_OK(status)) {
750                                 printf("write failed (%s)\n",
751                                        nt_errstr(status));
752                                 correct = False;
753                         }
754                 }
755                 else
756                 {
757                         sent = cli_read(c, fnum, buf_rd+count, count,
758                                                   sizeof(buf)-count);
759                         if (sent < 0)
760                         {
761                                 printf("read failed offset:%d size:%ld (%s)\n",
762                                        count, (unsigned long)sizeof(buf)-count,
763                                        cli_errstr(c));
764                                 correct = False;
765                                 sent = 0;
766                         }
767                         if (sent > 0)
768                         {
769                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
770                                 {
771                                         printf("read/write compare failed\n");
772                                         printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
773                                         correct = False;
774                                         break;
775                                 }
776                         }
777                 }
778
779         }
780
781         status = cli_close(c, fnum);
782         if (!NT_STATUS_IS_OK(status)) {
783                 printf("close failed (%s)\n", nt_errstr(status));
784                 correct = False;
785         }
786
787         return correct;
788 }
789
790 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
791 {
792         const char *lockfname = "\\torture2.lck";
793         uint16_t fnum1;
794         uint16_t fnum2;
795         int i;
796         char buf[131072];
797         char buf_rd[131072];
798         bool correct = True;
799         ssize_t bytes_read;
800         NTSTATUS status;
801
802         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
803         if (!NT_STATUS_IS_OK(status)) {
804                 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
805         }
806
807         status = cli_open(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
808                           DENY_NONE, &fnum1);
809         if (!NT_STATUS_IS_OK(status)) {
810                 printf("first open read/write of %s failed (%s)\n",
811                                 lockfname, nt_errstr(status));
812                 return False;
813         }
814
815         status = cli_open(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
816         if (!NT_STATUS_IS_OK(status)) {
817                 printf("second open read-only of %s failed (%s)\n",
818                                 lockfname, nt_errstr(status));
819                 cli_close(c1, fnum1);
820                 return False;
821         }
822
823         for (i = 0; i < torture_numops; i++)
824         {
825                 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
826                 if (i % 10 == 0) {
827                         printf("%d\r", i); fflush(stdout);
828                 }
829
830                 generate_random_buffer((unsigned char *)buf, buf_size);
831
832                 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
833                                       buf_size, NULL);
834                 if (!NT_STATUS_IS_OK(status)) {
835                         printf("write failed (%s)\n", nt_errstr(status));
836                         correct = False;
837                         break;
838                 }
839
840                 if ((bytes_read = cli_read(c2, fnum2, buf_rd, 0, buf_size)) != buf_size) {
841                         printf("read failed (%s)\n", cli_errstr(c2));
842                         printf("read %d, expected %ld\n", (int)bytes_read, 
843                                (unsigned long)buf_size); 
844                         correct = False;
845                         break;
846                 }
847
848                 if (memcmp(buf_rd, buf, buf_size) != 0)
849                 {
850                         printf("read/write compare failed\n");
851                         correct = False;
852                         break;
853                 }
854         }
855
856         status = cli_close(c2, fnum2);
857         if (!NT_STATUS_IS_OK(status)) {
858                 printf("close failed (%s)\n", nt_errstr(status));
859                 correct = False;
860         }
861
862         status = cli_close(c1, fnum1);
863         if (!NT_STATUS_IS_OK(status)) {
864                 printf("close failed (%s)\n", nt_errstr(status));
865                 correct = False;
866         }
867
868         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
869         if (!NT_STATUS_IS_OK(status)) {
870                 printf("unlink failed (%s)\n", nt_errstr(status));
871                 correct = False;
872         }
873
874         return correct;
875 }
876
877 static bool run_readwritetest(int dummy)
878 {
879         struct cli_state *cli1, *cli2;
880         bool test1, test2 = False;
881
882         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
883                 return False;
884         }
885         cli_sockopt(cli1, sockops);
886         cli_sockopt(cli2, sockops);
887
888         printf("starting readwritetest\n");
889
890         test1 = rw_torture2(cli1, cli2);
891         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
892
893         if (test1) {
894                 test2 = rw_torture2(cli1, cli1);
895                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
896         }
897
898         if (!torture_close_connection(cli1)) {
899                 test1 = False;
900         }
901
902         if (!torture_close_connection(cli2)) {
903                 test2 = False;
904         }
905
906         return (test1 && test2);
907 }
908
909 static bool run_readwritemulti(int dummy)
910 {
911         struct cli_state *cli;
912         bool test;
913
914         cli = current_cli;
915
916         cli_sockopt(cli, sockops);
917
918         printf("run_readwritemulti: fname %s\n", randomfname);
919         test = rw_torture3(cli, randomfname);
920
921         if (!torture_close_connection(cli)) {
922                 test = False;
923         }
924
925         return test;
926 }
927
928 static bool run_readwritelarge_internal(int max_xmit_k)
929 {
930         static struct cli_state *cli1;
931         uint16_t fnum1;
932         const char *lockfname = "\\large.dat";
933         SMB_OFF_T fsize;
934         char buf[126*1024];
935         bool correct = True;
936         NTSTATUS status;
937
938         if (!torture_open_connection(&cli1, 0)) {
939                 return False;
940         }
941         cli_sockopt(cli1, sockops);
942         memset(buf,'\0',sizeof(buf));
943
944         cli1->max_xmit = max_xmit_k*1024;
945
946         if (signing_state == Required) {
947                 /* Horrible cheat to force
948                    multiple signed outstanding
949                    packets against a Samba server.
950                 */
951                 cli1->is_samba = false;
952         }
953
954         printf("starting readwritelarge_internal\n");
955
956         cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
957
958         status = cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
959                           DENY_NONE, &fnum1);
960         if (!NT_STATUS_IS_OK(status)) {
961                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
962                 return False;
963         }
964
965         cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
966
967         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
968                                      NULL, NULL, NULL);
969         if (!NT_STATUS_IS_OK(status)) {
970                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
971                 correct = False;
972         }
973
974         if (fsize == sizeof(buf))
975                 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
976                        (unsigned long)fsize);
977         else {
978                 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
979                        (unsigned long)fsize);
980                 correct = False;
981         }
982
983         status = cli_close(cli1, fnum1);
984         if (!NT_STATUS_IS_OK(status)) {
985                 printf("close failed (%s)\n", nt_errstr(status));
986                 correct = False;
987         }
988
989         status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
990         if (!NT_STATUS_IS_OK(status)) {
991                 printf("unlink failed (%s)\n", nt_errstr(status));
992                 correct = False;
993         }
994
995         status = cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
996                           DENY_NONE, &fnum1);
997         if (!NT_STATUS_IS_OK(status)) {
998                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
999                 return False;
1000         }
1001
1002         cli1->max_xmit = 4*1024;
1003
1004         cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1005
1006         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1007                                      NULL, NULL, NULL);
1008         if (!NT_STATUS_IS_OK(status)) {
1009                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1010                 correct = False;
1011         }
1012
1013         if (fsize == sizeof(buf))
1014                 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1015                        (unsigned long)fsize);
1016         else {
1017                 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1018                        (unsigned long)fsize);
1019                 correct = False;
1020         }
1021
1022 #if 0
1023         /* ToDo - set allocation. JRA */
1024         if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1025                 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1026                 return False;
1027         }
1028         if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1029                                  NULL, NULL)) {
1030                 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1031                 correct = False;
1032         }
1033         if (fsize != 0)
1034                 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1035 #endif
1036
1037         status = cli_close(cli1, fnum1);
1038         if (!NT_STATUS_IS_OK(status)) {
1039                 printf("close failed (%s)\n", nt_errstr(status));
1040                 correct = False;
1041         }
1042
1043         if (!torture_close_connection(cli1)) {
1044                 correct = False;
1045         }
1046         return correct;
1047 }
1048
1049 static bool run_readwritelarge(int dummy)
1050 {
1051         return run_readwritelarge_internal(128);
1052 }
1053
1054 static bool run_readwritelarge_signtest(int dummy)
1055 {
1056         bool ret;
1057         signing_state = Required;
1058         ret = run_readwritelarge_internal(2);
1059         signing_state = Undefined;
1060         return ret;
1061 }
1062
1063 int line_count = 0;
1064 int nbio_id;
1065
1066 #define ival(s) strtol(s, NULL, 0)
1067
1068 /* run a test that simulates an approximate netbench client load */
1069 static bool run_netbench(int client)
1070 {
1071         struct cli_state *cli;
1072         int i;
1073         char line[1024];
1074         char cname[20];
1075         FILE *f;
1076         const char *params[20];
1077         bool correct = True;
1078
1079         cli = current_cli;
1080
1081         nbio_id = client;
1082
1083         cli_sockopt(cli, sockops);
1084
1085         nb_setup(cli);
1086
1087         slprintf(cname,sizeof(cname)-1, "client%d", client);
1088
1089         f = fopen(client_txt, "r");
1090
1091         if (!f) {
1092                 perror(client_txt);
1093                 return False;
1094         }
1095
1096         while (fgets(line, sizeof(line)-1, f)) {
1097                 char *saveptr;
1098                 line_count++;
1099
1100                 line[strlen(line)-1] = 0;
1101
1102                 /* printf("[%d] %s\n", line_count, line); */
1103
1104                 all_string_sub(line,"client1", cname, sizeof(line));
1105
1106                 /* parse the command parameters */
1107                 params[0] = strtok_r(line, " ", &saveptr);
1108                 i = 0;
1109                 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1110
1111                 params[i] = "";
1112
1113                 if (i < 2) continue;
1114
1115                 if (!strncmp(params[0],"SMB", 3)) {
1116                         printf("ERROR: You are using a dbench 1 load file\n");
1117                         exit(1);
1118                 }
1119
1120                 if (!strcmp(params[0],"NTCreateX")) {
1121                         nb_createx(params[1], ival(params[2]), ival(params[3]), 
1122                                    ival(params[4]));
1123                 } else if (!strcmp(params[0],"Close")) {
1124                         nb_close(ival(params[1]));
1125                 } else if (!strcmp(params[0],"Rename")) {
1126                         nb_rename(params[1], params[2]);
1127                 } else if (!strcmp(params[0],"Unlink")) {
1128                         nb_unlink(params[1]);
1129                 } else if (!strcmp(params[0],"Deltree")) {
1130                         nb_deltree(params[1]);
1131                 } else if (!strcmp(params[0],"Rmdir")) {
1132                         nb_rmdir(params[1]);
1133                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1134                         nb_qpathinfo(params[1]);
1135                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1136                         nb_qfileinfo(ival(params[1]));
1137                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1138                         nb_qfsinfo(ival(params[1]));
1139                 } else if (!strcmp(params[0],"FIND_FIRST")) {
1140                         nb_findfirst(params[1]);
1141                 } else if (!strcmp(params[0],"WriteX")) {
1142                         nb_writex(ival(params[1]), 
1143                                   ival(params[2]), ival(params[3]), ival(params[4]));
1144                 } else if (!strcmp(params[0],"ReadX")) {
1145                         nb_readx(ival(params[1]), 
1146                                   ival(params[2]), ival(params[3]), ival(params[4]));
1147                 } else if (!strcmp(params[0],"Flush")) {
1148                         nb_flush(ival(params[1]));
1149                 } else {
1150                         printf("Unknown operation %s\n", params[0]);
1151                         exit(1);
1152                 }
1153         }
1154         fclose(f);
1155
1156         nb_cleanup();
1157
1158         if (!torture_close_connection(cli)) {
1159                 correct = False;
1160         }
1161
1162         return correct;
1163 }
1164
1165
1166 /* run a test that simulates an approximate netbench client load */
1167 static bool run_nbench(int dummy)
1168 {
1169         double t;
1170         bool correct = True;
1171
1172         nbio_shmem(nprocs);
1173
1174         nbio_id = -1;
1175
1176         signal(SIGALRM, nb_alarm);
1177         alarm(1);
1178         t = create_procs(run_netbench, &correct);
1179         alarm(0);
1180
1181         printf("\nThroughput %g MB/sec\n", 
1182                1.0e-6 * nbio_total() / t);
1183         return correct;
1184 }
1185
1186
1187 /*
1188   This test checks for two things:
1189
1190   1) correct support for retaining locks over a close (ie. the server
1191      must not use posix semantics)
1192   2) support for lock timeouts
1193  */
1194 static bool run_locktest1(int dummy)
1195 {
1196         struct cli_state *cli1, *cli2;
1197         const char *fname = "\\lockt1.lck";
1198         uint16_t fnum1, fnum2, fnum3;
1199         time_t t1, t2;
1200         unsigned lock_timeout;
1201         NTSTATUS status;
1202
1203         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1204                 return False;
1205         }
1206         cli_sockopt(cli1, sockops);
1207         cli_sockopt(cli2, sockops);
1208
1209         printf("starting locktest1\n");
1210
1211         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1212
1213         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1214                           &fnum1);
1215         if (!NT_STATUS_IS_OK(status)) {
1216                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1217                 return False;
1218         }
1219
1220         status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1221         if (!NT_STATUS_IS_OK(status)) {
1222                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1223                 return False;
1224         }
1225
1226         status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1227         if (!NT_STATUS_IS_OK(status)) {
1228                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1229                 return False;
1230         }
1231
1232         if (!cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
1233                 printf("lock1 failed (%s)\n", cli_errstr(cli1));
1234                 return False;
1235         }
1236
1237
1238         if (cli_lock(cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
1239                 printf("lock2 succeeded! This is a locking bug\n");
1240                 return False;
1241         } else {
1242                 if (!check_error(__LINE__, cli2, ERRDOS, ERRlock, 
1243                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
1244         }
1245
1246
1247         lock_timeout = (1 + (random() % 20));
1248         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1249         t1 = time(NULL);
1250         if (cli_lock(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK)) {
1251                 printf("lock3 succeeded! This is a locking bug\n");
1252                 return False;
1253         } else {
1254                 if (!check_error(__LINE__, cli2, ERRDOS, ERRlock, 
1255                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
1256         }
1257         t2 = time(NULL);
1258
1259         if (ABS(t2 - t1) < lock_timeout-1) {
1260                 printf("error: This server appears not to support timed lock requests\n");
1261         }
1262
1263         printf("server slept for %u seconds for a %u second timeout\n",
1264                (unsigned int)(t2-t1), lock_timeout);
1265
1266         status = cli_close(cli1, fnum2);
1267         if (!NT_STATUS_IS_OK(status)) {
1268                 printf("close1 failed (%s)\n", nt_errstr(status));
1269                 return False;
1270         }
1271
1272         if (cli_lock(cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
1273                 printf("lock4 succeeded! This is a locking bug\n");
1274                 return False;
1275         } else {
1276                 if (!check_error(__LINE__, cli2, ERRDOS, ERRlock, 
1277                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
1278         }
1279
1280         status = cli_close(cli1, fnum1);
1281         if (!NT_STATUS_IS_OK(status)) {
1282                 printf("close2 failed (%s)\n", nt_errstr(status));
1283                 return False;
1284         }
1285
1286         status = cli_close(cli2, fnum3);
1287         if (!NT_STATUS_IS_OK(status)) {
1288                 printf("close3 failed (%s)\n", nt_errstr(status));
1289                 return False;
1290         }
1291
1292         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1293         if (!NT_STATUS_IS_OK(status)) {
1294                 printf("unlink failed (%s)\n", nt_errstr(status));
1295                 return False;
1296         }
1297
1298
1299         if (!torture_close_connection(cli1)) {
1300                 return False;
1301         }
1302
1303         if (!torture_close_connection(cli2)) {
1304                 return False;
1305         }
1306
1307         printf("Passed locktest1\n");
1308         return True;
1309 }
1310
1311 /*
1312   this checks to see if a secondary tconx can use open files from an
1313   earlier tconx
1314  */
1315 static bool run_tcon_test(int dummy)
1316 {
1317         static struct cli_state *cli;
1318         const char *fname = "\\tcontest.tmp";
1319         uint16 fnum1;
1320         uint16 cnum1, cnum2, cnum3;
1321         uint16 vuid1, vuid2;
1322         char buf[4];
1323         bool ret = True;
1324         NTSTATUS status;
1325
1326         memset(buf, '\0', sizeof(buf));
1327
1328         if (!torture_open_connection(&cli, 0)) {
1329                 return False;
1330         }
1331         cli_sockopt(cli, sockops);
1332
1333         printf("starting tcontest\n");
1334
1335         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1336
1337         status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1338         if (!NT_STATUS_IS_OK(status)) {
1339                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1340                 return False;
1341         }
1342
1343         cnum1 = cli->cnum;
1344         vuid1 = cli->vuid;
1345
1346         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1347         if (!NT_STATUS_IS_OK(status)) {
1348                 printf("initial write failed (%s)", nt_errstr(status));
1349                 return False;
1350         }
1351
1352         status = cli_tcon_andx(cli, share, "?????",
1353                                password, strlen(password)+1);
1354         if (!NT_STATUS_IS_OK(status)) {
1355                 printf("%s refused 2nd tree connect (%s)\n", host,
1356                        nt_errstr(status));
1357                 cli_shutdown(cli);
1358                 return False;
1359         }
1360
1361         cnum2 = cli->cnum;
1362         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1363         vuid2 = cli->vuid + 1;
1364
1365         /* try a write with the wrong tid */
1366         cli->cnum = cnum2;
1367
1368         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1369         if (NT_STATUS_IS_OK(status)) {
1370                 printf("* server allows write with wrong TID\n");
1371                 ret = False;
1372         } else {
1373                 printf("server fails write with wrong TID : %s\n",
1374                        nt_errstr(status));
1375         }
1376
1377
1378         /* try a write with an invalid tid */
1379         cli->cnum = cnum3;
1380
1381         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1382         if (NT_STATUS_IS_OK(status)) {
1383                 printf("* server allows write with invalid TID\n");
1384                 ret = False;
1385         } else {
1386                 printf("server fails write with invalid TID : %s\n",
1387                        nt_errstr(status));
1388         }
1389
1390         /* try a write with an invalid vuid */
1391         cli->vuid = vuid2;
1392         cli->cnum = cnum1;
1393
1394         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1395         if (NT_STATUS_IS_OK(status)) {
1396                 printf("* server allows write with invalid VUID\n");
1397                 ret = False;
1398         } else {
1399                 printf("server fails write with invalid VUID : %s\n",
1400                        nt_errstr(status));
1401         }
1402
1403         cli->cnum = cnum1;
1404         cli->vuid = vuid1;
1405
1406         status = cli_close(cli, fnum1);
1407         if (!NT_STATUS_IS_OK(status)) {
1408                 printf("close failed (%s)\n", nt_errstr(status));
1409                 return False;
1410         }
1411
1412         cli->cnum = cnum2;
1413
1414         status = cli_tdis(cli);
1415         if (!NT_STATUS_IS_OK(status)) {
1416                 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1417                 return False;
1418         }
1419
1420         cli->cnum = cnum1;
1421
1422         if (!torture_close_connection(cli)) {
1423                 return False;
1424         }
1425
1426         return ret;
1427 }
1428
1429
1430 /*
1431  checks for old style tcon support
1432  */
1433 static bool run_tcon2_test(int dummy)
1434 {
1435         static struct cli_state *cli;
1436         uint16 cnum, max_xmit;
1437         char *service;
1438         NTSTATUS status;
1439
1440         if (!torture_open_connection(&cli, 0)) {
1441                 return False;
1442         }
1443         cli_sockopt(cli, sockops);
1444
1445         printf("starting tcon2 test\n");
1446
1447         if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1448                 return false;
1449         }
1450
1451         status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1452
1453         SAFE_FREE(service);
1454
1455         if (!NT_STATUS_IS_OK(status)) {
1456                 printf("tcon2 failed : %s\n", nt_errstr(status));
1457         } else {
1458                 printf("tcon OK : max_xmit=%d cnum=%d\n",
1459                        (int)max_xmit, (int)cnum);
1460         }
1461
1462         if (!torture_close_connection(cli)) {
1463                 return False;
1464         }
1465
1466         printf("Passed tcon2 test\n");
1467         return True;
1468 }
1469
1470 static bool tcon_devtest(struct cli_state *cli,
1471                          const char *myshare, const char *devtype,
1472                          const char *return_devtype,
1473                          NTSTATUS expected_error)
1474 {
1475         NTSTATUS status;
1476         bool ret;
1477
1478         status = cli_tcon_andx(cli, myshare, devtype,
1479                                password, strlen(password)+1);
1480
1481         if (NT_STATUS_IS_OK(expected_error)) {
1482                 if (NT_STATUS_IS_OK(status)) {
1483                         if (strcmp(cli->dev, return_devtype) == 0) {
1484                                 ret = True;
1485                         } else { 
1486                                 printf("tconX to share %s with type %s "
1487                                        "succeeded but returned the wrong "
1488                                        "device type (got [%s] but should have got [%s])\n",
1489                                        myshare, devtype, cli->dev, return_devtype);
1490                                 ret = False;
1491                         }
1492                 } else {
1493                         printf("tconX to share %s with type %s "
1494                                "should have succeeded but failed\n",
1495                                myshare, devtype);
1496                         ret = False;
1497                 }
1498                 cli_tdis(cli);
1499         } else {
1500                 if (NT_STATUS_IS_OK(status)) {
1501                         printf("tconx to share %s with type %s "
1502                                "should have failed but succeeded\n",
1503                                myshare, devtype);
1504                         ret = False;
1505                 } else {
1506                         if (NT_STATUS_EQUAL(cli_nt_error(cli),
1507                                             expected_error)) {
1508                                 ret = True;
1509                         } else {
1510                                 printf("Returned unexpected error\n");
1511                                 ret = False;
1512                         }
1513                 }
1514         }
1515         return ret;
1516 }
1517
1518 /*
1519  checks for correct tconX support
1520  */
1521 static bool run_tcon_devtype_test(int dummy)
1522 {
1523         static struct cli_state *cli1 = NULL;
1524         int flags = 0;
1525         NTSTATUS status;
1526         bool ret = True;
1527
1528         status = cli_full_connection(&cli1, myname,
1529                                      host, NULL, port_to_use,
1530                                      NULL, NULL,
1531                                      username, workgroup,
1532                                      password, flags, signing_state);
1533
1534         if (!NT_STATUS_IS_OK(status)) {
1535                 printf("could not open connection\n");
1536                 return False;
1537         }
1538
1539         if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1540                 ret = False;
1541
1542         if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1543                 ret = False;
1544
1545         if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1546                 ret = False;
1547
1548         if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1549                 ret = False;
1550
1551         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1552                 ret = False;
1553
1554         if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1555                 ret = False;
1556
1557         if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1558                 ret = False;
1559
1560         if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1561                 ret = False;
1562
1563         if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1564                 ret = False;
1565
1566         if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1567                 ret = False;
1568
1569         cli_shutdown(cli1);
1570
1571         if (ret)
1572                 printf("Passed tcondevtest\n");
1573
1574         return ret;
1575 }
1576
1577
1578 /*
1579   This test checks that 
1580
1581   1) the server supports multiple locking contexts on the one SMB
1582   connection, distinguished by PID.  
1583
1584   2) the server correctly fails overlapping locks made by the same PID (this
1585      goes against POSIX behaviour, which is why it is tricky to implement)
1586
1587   3) the server denies unlock requests by an incorrect client PID
1588 */
1589 static bool run_locktest2(int dummy)
1590 {
1591         static struct cli_state *cli;
1592         const char *fname = "\\lockt2.lck";
1593         uint16_t fnum1, fnum2, fnum3;
1594         bool correct = True;
1595         NTSTATUS status;
1596
1597         if (!torture_open_connection(&cli, 0)) {
1598                 return False;
1599         }
1600
1601         cli_sockopt(cli, sockops);
1602
1603         printf("starting locktest2\n");
1604
1605         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1606
1607         cli_setpid(cli, 1);
1608
1609         status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1610         if (!NT_STATUS_IS_OK(status)) {
1611                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1612                 return False;
1613         }
1614
1615         status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1616         if (!NT_STATUS_IS_OK(status)) {
1617                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1618                 return False;
1619         }
1620
1621         cli_setpid(cli, 2);
1622
1623         status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1624         if (!NT_STATUS_IS_OK(status)) {
1625                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1626                 return False;
1627         }
1628
1629         cli_setpid(cli, 1);
1630
1631         if (!cli_lock(cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
1632                 printf("lock1 failed (%s)\n", cli_errstr(cli));
1633                 return False;
1634         }
1635
1636         if (cli_lock(cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
1637                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1638                 correct = False;
1639         } else {
1640                 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, 
1641                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
1642         }
1643
1644         if (cli_lock(cli, fnum2, 0, 4, 0, WRITE_LOCK)) {
1645                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1646                 correct = False;
1647         } else {
1648                 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, 
1649                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
1650         }
1651
1652         if (cli_lock(cli, fnum2, 0, 4, 0, READ_LOCK)) {
1653                 printf("READ lock2 succeeded! This is a locking bug\n");
1654                 correct = False;
1655         } else {
1656                 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, 
1657                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
1658         }
1659
1660         if (!cli_lock(cli, fnum1, 100, 4, 0, WRITE_LOCK)) {
1661                 printf("lock at 100 failed (%s)\n", cli_errstr(cli));
1662         }
1663         cli_setpid(cli, 2);
1664         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1665                 printf("unlock at 100 succeeded! This is a locking bug\n");
1666                 correct = False;
1667         }
1668
1669         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 0, 4))) {
1670                 printf("unlock1 succeeded! This is a locking bug\n");
1671                 correct = False;
1672         } else {
1673                 if (!check_error(__LINE__, cli, 
1674                                  ERRDOS, ERRlock, 
1675                                  NT_STATUS_RANGE_NOT_LOCKED)) return False;
1676         }
1677
1678         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 0, 8))) {
1679                 printf("unlock2 succeeded! This is a locking bug\n");
1680                 correct = False;
1681         } else {
1682                 if (!check_error(__LINE__, cli, 
1683                                  ERRDOS, ERRlock, 
1684                                  NT_STATUS_RANGE_NOT_LOCKED)) return False;
1685         }
1686
1687         if (cli_lock(cli, fnum3, 0, 4, 0, WRITE_LOCK)) {
1688                 printf("lock3 succeeded! This is a locking bug\n");
1689                 correct = False;
1690         } else {
1691                 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
1692         }
1693
1694         cli_setpid(cli, 1);
1695
1696         status = cli_close(cli, fnum1);
1697         if (!NT_STATUS_IS_OK(status)) {
1698                 printf("close1 failed (%s)\n", nt_errstr(status));
1699                 return False;
1700         }
1701
1702         status = cli_close(cli, fnum2);
1703         if (!NT_STATUS_IS_OK(status)) {
1704                 printf("close2 failed (%s)\n", nt_errstr(status));
1705                 return False;
1706         }
1707
1708         status = cli_close(cli, fnum3);
1709         if (!NT_STATUS_IS_OK(status)) {
1710                 printf("close3 failed (%s)\n", nt_errstr(status));
1711                 return False;
1712         }
1713
1714         if (!torture_close_connection(cli)) {
1715                 correct = False;
1716         }
1717
1718         printf("locktest2 finished\n");
1719
1720         return correct;
1721 }
1722
1723
1724 /*
1725   This test checks that 
1726
1727   1) the server supports the full offset range in lock requests
1728 */
1729 static bool run_locktest3(int dummy)
1730 {
1731         static struct cli_state *cli1, *cli2;
1732         const char *fname = "\\lockt3.lck";
1733         uint16_t fnum1, fnum2;
1734         int i;
1735         uint32 offset;
1736         bool correct = True;
1737         NTSTATUS status;
1738
1739 #define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
1740
1741         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1742                 return False;
1743         }
1744         cli_sockopt(cli1, sockops);
1745         cli_sockopt(cli2, sockops);
1746
1747         printf("starting locktest3\n");
1748
1749         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1750
1751         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1752                          &fnum1);
1753         if (!NT_STATUS_IS_OK(status)) {
1754                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1755                 return False;
1756         }
1757
1758         status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1759         if (!NT_STATUS_IS_OK(status)) {
1760                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1761                 return False;
1762         }
1763
1764         for (offset=i=0;i<torture_numops;i++) {
1765                 NEXT_OFFSET;
1766                 if (!cli_lock(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
1767                         printf("lock1 %d failed (%s)\n", 
1768                                i,
1769                                cli_errstr(cli1));
1770                         return False;
1771                 }
1772
1773                 if (!cli_lock(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
1774                         printf("lock2 %d failed (%s)\n", 
1775                                i,
1776                                cli_errstr(cli1));
1777                         return False;
1778                 }
1779         }
1780
1781         for (offset=i=0;i<torture_numops;i++) {
1782                 NEXT_OFFSET;
1783
1784                 if (cli_lock(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK)) {
1785                         printf("error: lock1 %d succeeded!\n", i);
1786                         return False;
1787                 }
1788
1789                 if (cli_lock(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK)) {
1790                         printf("error: lock2 %d succeeded!\n", i);
1791                         return False;
1792                 }
1793
1794                 if (cli_lock(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
1795                         printf("error: lock3 %d succeeded!\n", i);
1796                         return False;
1797                 }
1798
1799                 if (cli_lock(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
1800                         printf("error: lock4 %d succeeded!\n", i);
1801                         return False;
1802                 }
1803         }
1804
1805         for (offset=i=0;i<torture_numops;i++) {
1806                 NEXT_OFFSET;
1807
1808                 status = cli_unlock(cli1, fnum1, offset-1, 1);
1809                 if (!NT_STATUS_IS_OK(status)) {
1810                         printf("unlock1 %d failed (%s)\n", 
1811                                i,
1812                                nt_errstr(status));
1813                         return False;
1814                 }
1815
1816                 status = cli_unlock(cli2, fnum2, offset-2, 1);
1817                 if (!NT_STATUS_IS_OK(status)) {
1818                         printf("unlock2 %d failed (%s)\n", 
1819                                i,
1820                                nt_errstr(status));
1821                         return False;
1822                 }
1823         }
1824
1825         status = cli_close(cli1, fnum1);
1826         if (!NT_STATUS_IS_OK(status)) {
1827                 printf("close1 failed (%s)\n", nt_errstr(status));
1828                 return False;
1829         }
1830
1831         status = cli_close(cli2, fnum2);
1832         if (!NT_STATUS_IS_OK(status)) {
1833                 printf("close2 failed (%s)\n", nt_errstr(status));
1834                 return False;
1835         }
1836
1837         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1838         if (!NT_STATUS_IS_OK(status)) {
1839                 printf("unlink failed (%s)\n", nt_errstr(status));
1840                 return False;
1841         }
1842
1843         if (!torture_close_connection(cli1)) {
1844                 correct = False;
1845         }
1846
1847         if (!torture_close_connection(cli2)) {
1848                 correct = False;
1849         }
1850
1851         printf("finished locktest3\n");
1852
1853         return correct;
1854 }
1855
1856 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1857         printf("** "); correct = False; \
1858         }
1859
1860 /*
1861   looks at overlapping locks
1862 */
1863 static bool run_locktest4(int dummy)
1864 {
1865         static struct cli_state *cli1, *cli2;
1866         const char *fname = "\\lockt4.lck";
1867         uint16_t fnum1, fnum2, f;
1868         bool ret;
1869         char buf[1000];
1870         bool correct = True;
1871         NTSTATUS status;
1872
1873         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1874                 return False;
1875         }
1876
1877         cli_sockopt(cli1, sockops);
1878         cli_sockopt(cli2, sockops);
1879
1880         printf("starting locktest4\n");
1881
1882         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1883
1884         cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1885         cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1886
1887         memset(buf, 0, sizeof(buf));
1888
1889         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1890                               NULL);
1891         if (!NT_STATUS_IS_OK(status)) {
1892                 printf("Failed to create file: %s\n", nt_errstr(status));
1893                 correct = False;
1894                 goto fail;
1895         }
1896
1897         ret = cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
1898               cli_lock(cli1, fnum1, 2, 4, 0, WRITE_LOCK);
1899         EXPECTED(ret, False);
1900         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1901
1902         ret = cli_lock(cli1, fnum1, 10, 4, 0, READ_LOCK) &&
1903               cli_lock(cli1, fnum1, 12, 4, 0, READ_LOCK);
1904         EXPECTED(ret, True);
1905         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1906
1907         ret = cli_lock(cli1, fnum1, 20, 4, 0, WRITE_LOCK) &&
1908               cli_lock(cli2, fnum2, 22, 4, 0, WRITE_LOCK);
1909         EXPECTED(ret, False);
1910         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1911
1912         ret = cli_lock(cli1, fnum1, 30, 4, 0, READ_LOCK) &&
1913               cli_lock(cli2, fnum2, 32, 4, 0, READ_LOCK);
1914         EXPECTED(ret, True);
1915         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1916
1917         ret = (cli_setpid(cli1, 1), cli_lock(cli1, fnum1, 40, 4, 0, WRITE_LOCK)) &&
1918               (cli_setpid(cli1, 2), cli_lock(cli1, fnum1, 42, 4, 0, WRITE_LOCK));
1919         EXPECTED(ret, False);
1920         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1921
1922         ret = (cli_setpid(cli1, 1), cli_lock(cli1, fnum1, 50, 4, 0, READ_LOCK)) &&
1923               (cli_setpid(cli1, 2), cli_lock(cli1, fnum1, 52, 4, 0, READ_LOCK));
1924         EXPECTED(ret, True);
1925         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1926
1927         ret = cli_lock(cli1, fnum1, 60, 4, 0, READ_LOCK) &&
1928               cli_lock(cli1, fnum1, 60, 4, 0, READ_LOCK);
1929         EXPECTED(ret, True);
1930         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1931
1932         ret = cli_lock(cli1, fnum1, 70, 4, 0, WRITE_LOCK) &&
1933               cli_lock(cli1, fnum1, 70, 4, 0, WRITE_LOCK);
1934         EXPECTED(ret, False);
1935         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1936
1937         ret = cli_lock(cli1, fnum1, 80, 4, 0, READ_LOCK) &&
1938               cli_lock(cli1, fnum1, 80, 4, 0, WRITE_LOCK);
1939         EXPECTED(ret, False);
1940         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1941
1942         ret = cli_lock(cli1, fnum1, 90, 4, 0, WRITE_LOCK) &&
1943               cli_lock(cli1, fnum1, 90, 4, 0, READ_LOCK);
1944         EXPECTED(ret, True);
1945         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1946
1947         ret = (cli_setpid(cli1, 1), cli_lock(cli1, fnum1, 100, 4, 0, WRITE_LOCK)) &&
1948               (cli_setpid(cli1, 2), cli_lock(cli1, fnum1, 100, 4, 0, READ_LOCK));
1949         EXPECTED(ret, False);
1950         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1951
1952         ret = cli_lock(cli1, fnum1, 110, 4, 0, READ_LOCK) &&
1953               cli_lock(cli1, fnum1, 112, 4, 0, READ_LOCK) &&
1954               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
1955         EXPECTED(ret, False);
1956         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
1957
1958
1959         ret = cli_lock(cli1, fnum1, 120, 4, 0, WRITE_LOCK) &&
1960               (cli_read(cli2, fnum2, buf, 120, 4) == 4);
1961         EXPECTED(ret, False);
1962         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
1963
1964         ret = cli_lock(cli1, fnum1, 130, 4, 0, READ_LOCK);
1965         if (ret) {
1966                 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
1967                                       NULL);
1968                 ret = NT_STATUS_IS_OK(status);
1969         }
1970         EXPECTED(ret, False);
1971         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
1972
1973
1974         ret = cli_lock(cli1, fnum1, 140, 4, 0, READ_LOCK) &&
1975               cli_lock(cli1, fnum1, 140, 4, 0, READ_LOCK) &&
1976               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
1977               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
1978         EXPECTED(ret, True);
1979         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
1980
1981
1982         ret = cli_lock(cli1, fnum1, 150, 4, 0, WRITE_LOCK) &&
1983               cli_lock(cli1, fnum1, 150, 4, 0, READ_LOCK) &&
1984               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
1985               (cli_read(cli2, fnum2, buf, 150, 4) == 4) &&
1986               !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
1987                                              150, 4, NULL))) &&
1988               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
1989         EXPECTED(ret, True);
1990         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
1991
1992         ret = cli_lock(cli1, fnum1, 160, 4, 0, READ_LOCK) &&
1993               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
1994               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
1995                                            160, 4, NULL)) &&
1996               (cli_read(cli2, fnum2, buf, 160, 4) == 4);                
1997         EXPECTED(ret, True);
1998         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
1999
2000         ret = cli_lock(cli1, fnum1, 170, 4, 0, WRITE_LOCK) &&
2001               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2002               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2003                                            170, 4, NULL)) &&
2004               (cli_read(cli2, fnum2, buf, 170, 4) == 4);                
2005         EXPECTED(ret, True);
2006         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2007
2008         ret = cli_lock(cli1, fnum1, 190, 4, 0, WRITE_LOCK) &&
2009               cli_lock(cli1, fnum1, 190, 4, 0, READ_LOCK) &&
2010               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2011               !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2012                                             190, 4, NULL)) &&
2013               (cli_read(cli2, fnum2, buf, 190, 4) == 4);                
2014         EXPECTED(ret, True);
2015         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2016
2017         cli_close(cli1, fnum1);
2018         cli_close(cli2, fnum2);
2019         cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2020         cli_open(cli1, fname, O_RDWR, DENY_NONE, &f);
2021         ret = cli_lock(cli1, fnum1, 0, 8, 0, READ_LOCK) &&
2022               cli_lock(cli1, f, 0, 1, 0, READ_LOCK) &&
2023               NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2024               NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2025               cli_lock(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2026         cli_close(cli1, f);
2027         cli_close(cli1, fnum1);
2028         EXPECTED(ret, True);
2029         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2030
2031  fail:
2032         cli_close(cli1, fnum1);
2033         cli_close(cli2, fnum2);
2034         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2035         torture_close_connection(cli1);
2036         torture_close_connection(cli2);
2037
2038         printf("finished locktest4\n");
2039         return correct;
2040 }
2041
2042 /*
2043   looks at lock upgrade/downgrade.
2044 */
2045 static bool run_locktest5(int dummy)
2046 {
2047         static struct cli_state *cli1, *cli2;
2048         const char *fname = "\\lockt5.lck";
2049         uint16_t fnum1, fnum2, fnum3;
2050         bool ret;
2051         char buf[1000];
2052         bool correct = True;
2053         NTSTATUS status;
2054
2055         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2056                 return False;
2057         }
2058
2059         cli_sockopt(cli1, sockops);
2060         cli_sockopt(cli2, sockops);
2061
2062         printf("starting locktest5\n");
2063
2064         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2065
2066         cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2067         cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2068         cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2069
2070         memset(buf, 0, sizeof(buf));
2071
2072         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2073                               NULL);
2074         if (!NT_STATUS_IS_OK(status)) {
2075                 printf("Failed to create file: %s\n", nt_errstr(status));
2076                 correct = False;
2077                 goto fail;
2078         }
2079
2080         /* Check for NT bug... */
2081         ret = cli_lock(cli1, fnum1, 0, 8, 0, READ_LOCK) &&
2082                   cli_lock(cli1, fnum3, 0, 1, 0, READ_LOCK);
2083         cli_close(cli1, fnum1);
2084         cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2085         ret = cli_lock(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2086         EXPECTED(ret, True);
2087         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2088         cli_close(cli1, fnum1);
2089         cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2090         cli_unlock(cli1, fnum3, 0, 1);
2091
2092         ret = cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
2093               cli_lock(cli1, fnum1, 1, 1, 0, READ_LOCK);
2094         EXPECTED(ret, True);
2095         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2096
2097         ret = cli_lock(cli2, fnum2, 0, 4, 0, READ_LOCK);
2098         EXPECTED(ret, False);
2099
2100         printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2101
2102         /* Unlock the process 2 lock. */
2103         cli_unlock(cli2, fnum2, 0, 4);
2104
2105         ret = cli_lock(cli1, fnum3, 0, 4, 0, READ_LOCK);
2106         EXPECTED(ret, False);
2107
2108         printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2109
2110         /* Unlock the process 1 fnum3 lock. */
2111         cli_unlock(cli1, fnum3, 0, 4);
2112
2113         /* Stack 2 more locks here. */
2114         ret = cli_lock(cli1, fnum1, 0, 4, 0, READ_LOCK) &&
2115                   cli_lock(cli1, fnum1, 0, 4, 0, READ_LOCK);
2116
2117         EXPECTED(ret, True);
2118         printf("the same process %s stack read locks\n", ret?"can":"cannot");
2119
2120         /* Unlock the first process lock, then check this was the WRITE lock that was
2121                 removed. */
2122
2123         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2124                         cli_lock(cli2, fnum2, 0, 4, 0, READ_LOCK);
2125
2126         EXPECTED(ret, True);
2127         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2128
2129         /* Unlock the process 2 lock. */
2130         cli_unlock(cli2, fnum2, 0, 4);
2131
2132         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2133
2134         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2135                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2136                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2137
2138         EXPECTED(ret, True);
2139         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
2140
2141         /* Ensure the next unlock fails. */
2142         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2143         EXPECTED(ret, False);
2144         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
2145
2146         /* Ensure connection 2 can get a write lock. */
2147         ret = cli_lock(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2148         EXPECTED(ret, True);
2149
2150         printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2151
2152
2153  fail:
2154         cli_close(cli1, fnum1);
2155         cli_close(cli2, fnum2);
2156         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2157         if (!torture_close_connection(cli1)) {
2158                 correct = False;
2159         }
2160         if (!torture_close_connection(cli2)) {
2161                 correct = False;
2162         }
2163
2164         printf("finished locktest5\n");
2165
2166         return correct;
2167 }
2168
2169 /*
2170   tries the unusual lockingX locktype bits
2171 */
2172 static bool run_locktest6(int dummy)
2173 {
2174         static struct cli_state *cli;
2175         const char *fname[1] = { "\\lock6.txt" };
2176         int i;
2177         uint16_t fnum;
2178         NTSTATUS status;
2179
2180         if (!torture_open_connection(&cli, 0)) {
2181                 return False;
2182         }
2183
2184         cli_sockopt(cli, sockops);
2185
2186         printf("starting locktest6\n");
2187
2188         for (i=0;i<1;i++) {
2189                 printf("Testing %s\n", fname[i]);
2190
2191                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2192
2193                 cli_open(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2194                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2195                 cli_close(cli, fnum);
2196                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2197
2198                 cli_open(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2199                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2200                 cli_close(cli, fnum);
2201                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2202
2203                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2204         }
2205
2206         torture_close_connection(cli);
2207
2208         printf("finished locktest6\n");
2209         return True;
2210 }
2211
2212 static bool run_locktest7(int dummy)
2213 {
2214         struct cli_state *cli1;
2215         const char *fname = "\\lockt7.lck";
2216         uint16_t fnum1;
2217         char buf[200];
2218         bool correct = False;
2219         NTSTATUS status;
2220
2221         if (!torture_open_connection(&cli1, 0)) {
2222                 return False;
2223         }
2224
2225         cli_sockopt(cli1, sockops);
2226
2227         printf("starting locktest7\n");
2228
2229         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2230
2231         cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2232
2233         memset(buf, 0, sizeof(buf));
2234
2235         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2236                               NULL);
2237         if (!NT_STATUS_IS_OK(status)) {
2238                 printf("Failed to create file: %s\n", nt_errstr(status));
2239                 goto fail;
2240         }
2241
2242         cli_setpid(cli1, 1);
2243
2244         if (!cli_lock(cli1, fnum1, 130, 4, 0, READ_LOCK)) {
2245                 printf("Unable to apply read lock on range 130:4, error was %s\n", cli_errstr(cli1));
2246                 goto fail;
2247         } else {
2248                 printf("pid1 successfully locked range 130:4 for READ\n");
2249         }
2250
2251         if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2252                 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2253                 goto fail;
2254         } else {
2255                 printf("pid1 successfully read the range 130:4\n");
2256         }
2257
2258         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2259         if (!NT_STATUS_IS_OK(status)) {
2260                 printf("pid1 unable to write to the range 130:4, error was "
2261                        "%s\n", nt_errstr(status));
2262                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2263                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2264                         goto fail;
2265                 }
2266         } else {
2267                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2268                 goto fail;
2269         }
2270
2271         cli_setpid(cli1, 2);
2272
2273         if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2274                 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2275         } else {
2276                 printf("pid2 successfully read the range 130:4\n");
2277         }
2278
2279         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2280         if (!NT_STATUS_IS_OK(status)) {
2281                 printf("pid2 unable to write to the range 130:4, error was "
2282                        "%s\n", nt_errstr(status));
2283                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2284                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2285                         goto fail;
2286                 }
2287         } else {
2288                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2289                 goto fail;
2290         }
2291
2292         cli_setpid(cli1, 1);
2293         cli_unlock(cli1, fnum1, 130, 4);
2294
2295         if (!cli_lock(cli1, fnum1, 130, 4, 0, WRITE_LOCK)) {
2296                 printf("Unable to apply write lock on range 130:4, error was %s\n", cli_errstr(cli1));
2297                 goto fail;
2298         } else {
2299                 printf("pid1 successfully locked range 130:4 for WRITE\n");
2300         }
2301
2302         if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2303                 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2304                 goto fail;
2305         } else {
2306                 printf("pid1 successfully read the range 130:4\n");
2307         }
2308
2309         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2310         if (!NT_STATUS_IS_OK(status)) {
2311                 printf("pid1 unable to write to the range 130:4, error was "
2312                        "%s\n", nt_errstr(status));
2313                 goto fail;
2314         } else {
2315                 printf("pid1 successfully wrote to the range 130:4\n");
2316         }
2317
2318         cli_setpid(cli1, 2);
2319
2320         if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2321                 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2322                 if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
2323                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2324                         goto fail;
2325                 }
2326         } else {
2327                 printf("pid2 successfully read the range 130:4 (should be denied)\n");
2328                 goto fail;
2329         }
2330
2331         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2332         if (!NT_STATUS_IS_OK(status)) {
2333                 printf("pid2 unable to write to the range 130:4, error was "
2334                        "%s\n", nt_errstr(status));
2335                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2336                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2337                         goto fail;
2338                 }
2339         } else {
2340                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2341                 goto fail;
2342         }
2343
2344         cli_unlock(cli1, fnum1, 130, 0);
2345         correct = True;
2346
2347 fail:
2348         cli_close(cli1, fnum1);
2349         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2350         torture_close_connection(cli1);
2351
2352         printf("finished locktest7\n");
2353         return correct;
2354 }
2355
2356 /*
2357  * This demonstrates a problem with our use of GPFS share modes: A file
2358  * descriptor sitting in the pending close queue holding a GPFS share mode
2359  * blocks opening a file another time. Happens with Word 2007 temp files.
2360  * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2361  * open is denied with NT_STATUS_SHARING_VIOLATION.
2362  */
2363
2364 static bool run_locktest8(int dummy)
2365 {
2366         struct cli_state *cli1;
2367         const char *fname = "\\lockt8.lck";
2368         uint16_t fnum1, fnum2;
2369         char buf[200];
2370         bool correct = False;
2371         NTSTATUS status;
2372
2373         if (!torture_open_connection(&cli1, 0)) {
2374                 return False;
2375         }
2376
2377         cli_sockopt(cli1, sockops);
2378
2379         printf("starting locktest8\n");
2380
2381         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2382
2383         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2384                           &fnum1);
2385         if (!NT_STATUS_IS_OK(status)) {
2386                 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2387                 return false;
2388         }
2389
2390         memset(buf, 0, sizeof(buf));
2391
2392         status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2393         if (!NT_STATUS_IS_OK(status)) {
2394                 d_fprintf(stderr, "cli_open second time returned %s\n",
2395                           nt_errstr(status));
2396                 goto fail;
2397         }
2398
2399         if (!cli_lock(cli1, fnum2, 1, 1, 0, READ_LOCK)) {
2400                 printf("Unable to apply read lock on range 1:1, error was "
2401                        "%s\n", cli_errstr(cli1));
2402                 goto fail;
2403         }
2404
2405         status = cli_close(cli1, fnum1);
2406         if (!NT_STATUS_IS_OK(status)) {
2407                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2408                 goto fail;
2409         }
2410
2411         status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2412         if (!NT_STATUS_IS_OK(status)) {
2413                 d_fprintf(stderr, "cli_open third time returned %s\n",
2414                           nt_errstr(status));
2415                 goto fail;
2416         }
2417
2418         correct = true;
2419
2420 fail:
2421         cli_close(cli1, fnum1);
2422         cli_close(cli1, fnum2);
2423         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2424         torture_close_connection(cli1);
2425
2426         printf("finished locktest8\n");
2427         return correct;
2428 }
2429
2430 /*
2431  * This test is designed to be run in conjunction with
2432  * external NFS or POSIX locks taken in the filesystem.
2433  * It checks that the smbd server will block until the
2434  * lock is released and then acquire it. JRA.
2435  */
2436
2437 static bool got_alarm;
2438 static int alarm_fd;
2439
2440 static void alarm_handler(int dummy)
2441 {
2442         got_alarm = True;
2443 }
2444
2445 static void alarm_handler_parent(int dummy)
2446 {
2447         close(alarm_fd);
2448 }
2449
2450 static void do_local_lock(int read_fd, int write_fd)
2451 {
2452         int fd;
2453         char c = '\0';
2454         struct flock lock;
2455         const char *local_pathname = NULL;
2456         int ret;
2457
2458         local_pathname = talloc_asprintf(talloc_tos(),
2459                         "%s/lockt9.lck", local_path);
2460         if (!local_pathname) {
2461                 printf("child: alloc fail\n");
2462                 exit(1);
2463         }
2464
2465         unlink(local_pathname);
2466         fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2467         if (fd == -1) {
2468                 printf("child: open of %s failed %s.\n",
2469                         local_pathname, strerror(errno));
2470                 exit(1);
2471         }
2472
2473         /* Now take a fcntl lock. */
2474         lock.l_type = F_WRLCK;
2475         lock.l_whence = SEEK_SET;
2476         lock.l_start = 0;
2477         lock.l_len = 4;
2478         lock.l_pid = getpid();
2479
2480         ret = fcntl(fd,F_SETLK,&lock);
2481         if (ret == -1) {
2482                 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2483                         local_pathname, strerror(errno));
2484                 exit(1);
2485         } else {
2486                 printf("child: got lock 0:4 on file %s.\n",
2487                         local_pathname );
2488                 fflush(stdout);
2489         }
2490
2491         CatchSignal(SIGALRM, alarm_handler);
2492         alarm(5);
2493         /* Signal the parent. */
2494         if (write(write_fd, &c, 1) != 1) {
2495                 printf("child: start signal fail %s.\n",
2496                         strerror(errno));
2497                 exit(1);
2498         }
2499         alarm(0);
2500
2501         alarm(10);
2502         /* Wait for the parent to be ready. */
2503         if (read(read_fd, &c, 1) != 1) {
2504                 printf("child: reply signal fail %s.\n",
2505                         strerror(errno));
2506                 exit(1);
2507         }
2508         alarm(0);
2509
2510         sleep(5);
2511         close(fd);
2512         printf("child: released lock 0:4 on file %s.\n",
2513                 local_pathname );
2514         fflush(stdout);
2515         exit(0);
2516 }
2517
2518 static bool run_locktest9(int dummy)
2519 {
2520         struct cli_state *cli1;
2521         const char *fname = "\\lockt9.lck";
2522         uint16_t fnum;
2523         bool correct = False;
2524         int pipe_in[2], pipe_out[2];
2525         pid_t child_pid;
2526         char c = '\0';
2527         int ret;
2528         struct timeval start;
2529         double seconds;
2530         NTSTATUS status;
2531
2532         printf("starting locktest9\n");
2533
2534         if (local_path == NULL) {
2535                 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2536                 return false;
2537         }
2538
2539         if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2540                 return false;
2541         }
2542
2543         child_pid = fork();
2544         if (child_pid == -1) {
2545                 return false;
2546         }
2547
2548         if (child_pid == 0) {
2549                 /* Child. */
2550                 do_local_lock(pipe_out[0], pipe_in[1]);
2551                 exit(0);
2552         }
2553
2554         close(pipe_out[0]);
2555         close(pipe_in[1]);
2556         pipe_out[0] = -1;
2557         pipe_in[1] = -1;
2558
2559         /* Parent. */
2560         ret = read(pipe_in[0], &c, 1);
2561         if (ret != 1) {
2562                 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2563                         strerror(errno));
2564                 return false;
2565         }
2566
2567         if (!torture_open_connection(&cli1, 0)) {
2568                 return false;
2569         }
2570
2571         cli_sockopt(cli1, sockops);
2572
2573         status = cli_open(cli1, fname, O_RDWR, DENY_NONE,
2574                           &fnum);
2575         if (!NT_STATUS_IS_OK(status)) {
2576                 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2577                 return false;
2578         }
2579
2580         /* Ensure the child has the lock. */
2581         if (cli_lock(cli1, fnum, 0, 4, 0, WRITE_LOCK)) {
2582                 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2583                 goto fail;
2584         } else {
2585                 d_printf("Child has the lock.\n");
2586         }
2587
2588         /* Tell the child to wait 5 seconds then exit. */
2589         ret = write(pipe_out[1], &c, 1);
2590         if (ret != 1) {
2591                 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2592                         strerror(errno));
2593                 goto fail;
2594         }
2595
2596         /* Wait 20 seconds for the lock. */
2597         alarm_fd = cli1->fd;
2598         CatchSignal(SIGALRM, alarm_handler_parent);
2599         alarm(20);
2600
2601         start = timeval_current();
2602
2603         if (!cli_lock(cli1, fnum, 0, 4, -1, WRITE_LOCK)) {
2604                 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2605                        "%s\n", cli_errstr(cli1));
2606                 goto fail_nofd;
2607         }
2608         alarm(0);
2609
2610         seconds = timeval_elapsed(&start);
2611
2612         printf("Parent got the lock after %.2f seconds.\n",
2613                 seconds);
2614
2615         status = cli_close(cli1, fnum);
2616         if (!NT_STATUS_IS_OK(status)) {
2617                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2618                 goto fail;
2619         }
2620
2621         correct = true;
2622
2623 fail:
2624         cli_close(cli1, fnum);
2625         torture_close_connection(cli1);
2626
2627 fail_nofd:
2628
2629         printf("finished locktest9\n");
2630         return correct;
2631 }
2632
2633 /*
2634 test whether fnums and tids open on one VC are available on another (a major
2635 security hole)
2636 */
2637 static bool run_fdpasstest(int dummy)
2638 {
2639         struct cli_state *cli1, *cli2;
2640         const char *fname = "\\fdpass.tst";
2641         uint16_t fnum1;
2642         char buf[1024];
2643         NTSTATUS status;
2644
2645         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2646                 return False;
2647         }
2648         cli_sockopt(cli1, sockops);
2649         cli_sockopt(cli2, sockops);
2650
2651         printf("starting fdpasstest\n");
2652
2653         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2654
2655         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2656                           &fnum1);
2657         if (!NT_STATUS_IS_OK(status)) {
2658                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2659                 return False;
2660         }
2661
2662         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2663                               13, NULL);
2664         if (!NT_STATUS_IS_OK(status)) {
2665                 printf("write failed (%s)\n", nt_errstr(status));
2666                 return False;
2667         }
2668
2669         cli2->vuid = cli1->vuid;
2670         cli2->cnum = cli1->cnum;
2671         cli2->pid = cli1->pid;
2672
2673         if (cli_read(cli2, fnum1, buf, 0, 13) == 13) {
2674                 printf("read succeeded! nasty security hole [%s]\n",
2675                        buf);
2676                 return False;
2677         }
2678
2679         cli_close(cli1, fnum1);
2680         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2681
2682         torture_close_connection(cli1);
2683         torture_close_connection(cli2);
2684
2685         printf("finished fdpasstest\n");
2686         return True;
2687 }
2688
2689 static bool run_fdsesstest(int dummy)
2690 {
2691         struct cli_state *cli;
2692         uint16 new_vuid;
2693         uint16 saved_vuid;
2694         uint16 new_cnum;
2695         uint16 saved_cnum;
2696         const char *fname = "\\fdsess.tst";
2697         const char *fname1 = "\\fdsess1.tst";
2698         uint16_t fnum1;
2699         uint16_t fnum2;
2700         char buf[1024];
2701         bool ret = True;
2702         NTSTATUS status;
2703
2704         if (!torture_open_connection(&cli, 0))
2705                 return False;
2706         cli_sockopt(cli, sockops);
2707
2708         if (!torture_cli_session_setup2(cli, &new_vuid))
2709                 return False;
2710
2711         saved_cnum = cli->cnum;
2712         if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, share, "?????", "", 1)))
2713                 return False;
2714         new_cnum = cli->cnum;
2715         cli->cnum = saved_cnum;
2716
2717         printf("starting fdsesstest\n");
2718
2719         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2720         cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2721
2722         status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2723         if (!NT_STATUS_IS_OK(status)) {
2724                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2725                 return False;
2726         }
2727
2728         status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2729                               NULL);
2730         if (!NT_STATUS_IS_OK(status)) {
2731                 printf("write failed (%s)\n", nt_errstr(status));
2732                 return False;
2733         }
2734
2735         saved_vuid = cli->vuid;
2736         cli->vuid = new_vuid;
2737
2738         if (cli_read(cli, fnum1, buf, 0, 13) == 13) {
2739                 printf("read succeeded with different vuid! nasty security hole [%s]\n",
2740                        buf);
2741                 ret = False;
2742         }
2743         /* Try to open a file with different vuid, samba cnum. */
2744         if (NT_STATUS_IS_OK(cli_open(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2745                 printf("create with different vuid, same cnum succeeded.\n");
2746                 cli_close(cli, fnum2);
2747                 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2748         } else {
2749                 printf("create with different vuid, same cnum failed.\n");
2750                 printf("This will cause problems with service clients.\n");
2751                 ret = False;
2752         }
2753
2754         cli->vuid = saved_vuid;
2755
2756         /* Try with same vuid, different cnum. */
2757         cli->cnum = new_cnum;
2758
2759         if (cli_read(cli, fnum1, buf, 0, 13) == 13) {
2760                 printf("read succeeded with different cnum![%s]\n",
2761                        buf);
2762                 ret = False;
2763         }
2764
2765         cli->cnum = saved_cnum;
2766         cli_close(cli, fnum1);
2767         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2768
2769         torture_close_connection(cli);
2770
2771         printf("finished fdsesstest\n");
2772         return ret;
2773 }
2774
2775 /*
2776   This test checks that 
2777
2778   1) the server does not allow an unlink on a file that is open
2779 */
2780 static bool run_unlinktest(int dummy)
2781 {
2782         struct cli_state *cli;
2783         const char *fname = "\\unlink.tst";
2784         uint16_t fnum;
2785         bool correct = True;
2786         NTSTATUS status;
2787
2788         if (!torture_open_connection(&cli, 0)) {
2789                 return False;
2790         }
2791
2792         cli_sockopt(cli, sockops);
2793
2794         printf("starting unlink test\n");
2795
2796         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2797
2798         cli_setpid(cli, 1);
2799
2800         status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2801         if (!NT_STATUS_IS_OK(status)) {
2802                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2803                 return False;
2804         }
2805
2806         if (NT_STATUS_IS_OK(cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN))) {
2807                 printf("error: server allowed unlink on an open file\n");
2808                 correct = False;
2809         } else {
2810                 correct = check_error(__LINE__, cli, ERRDOS, ERRbadshare, 
2811                                       NT_STATUS_SHARING_VIOLATION);
2812         }
2813
2814         cli_close(cli, fnum);
2815         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2816
2817         if (!torture_close_connection(cli)) {
2818                 correct = False;
2819         }
2820
2821         printf("unlink test finished\n");
2822
2823         return correct;
2824 }
2825
2826
2827 /*
2828 test how many open files this server supports on the one socket
2829 */
2830 static bool run_maxfidtest(int dummy)
2831 {
2832         struct cli_state *cli;
2833         fstring fname;
2834         uint16_t fnums[0x11000];
2835         int i;
2836         int retries=4;
2837         bool correct = True;
2838         NTSTATUS status;
2839
2840         cli = current_cli;
2841
2842         if (retries <= 0) {
2843                 printf("failed to connect\n");
2844                 return False;
2845         }
2846
2847         cli_sockopt(cli, sockops);
2848
2849         for (i=0; i<0x11000; i++) {
2850                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2851                 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2852                                   &fnums[i]);
2853                 if (!NT_STATUS_IS_OK(status)) {
2854                         printf("open of %s failed (%s)\n", 
2855                                fname, nt_errstr(status));
2856                         printf("maximum fnum is %d\n", i);
2857                         break;
2858                 }
2859                 printf("%6d\r", i);
2860         }
2861         printf("%6d\n", i);
2862         i--;
2863
2864         printf("cleaning up\n");
2865         for (;i>=0;i--) {
2866                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2867                 cli_close(cli, fnums[i]);
2868
2869                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2870                 if (!NT_STATUS_IS_OK(status)) {
2871                         printf("unlink of %s failed (%s)\n", 
2872                                fname, nt_errstr(status));
2873                         correct = False;
2874                 }
2875                 printf("%6d\r", i);
2876         }
2877         printf("%6d\n", 0);
2878
2879         printf("maxfid test finished\n");
2880         if (!torture_close_connection(cli)) {
2881                 correct = False;
2882         }
2883         return correct;
2884 }
2885
2886 /* generate a random buffer */
2887 static void rand_buf(char *buf, int len)
2888 {
2889         while (len--) {
2890                 *buf = (char)sys_random();
2891                 buf++;
2892         }
2893 }
2894
2895 /* send smb negprot commands, not reading the response */
2896 static bool run_negprot_nowait(int dummy)
2897 {
2898         struct tevent_context *ev;
2899         int i;
2900         struct cli_state *cli;
2901         bool correct = True;
2902
2903         printf("starting negprot nowait test\n");
2904
2905         ev = tevent_context_init(talloc_tos());
2906         if (ev == NULL) {
2907                 return false;
2908         }
2909
2910         if (!(cli = open_nbt_connection())) {
2911                 TALLOC_FREE(ev);
2912                 return False;
2913         }
2914
2915         for (i=0;i<50000;i++) {
2916                 struct tevent_req *req;
2917
2918                 req = cli_negprot_send(ev, ev, cli);
2919                 if (req == NULL) {
2920                         TALLOC_FREE(ev);
2921                         return false;
2922                 }
2923                 if (!tevent_req_poll(req, ev)) {
2924                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
2925                                   strerror(errno));
2926                         TALLOC_FREE(ev);
2927                         return false;
2928                 }
2929                 TALLOC_FREE(req);
2930         }
2931
2932         if (torture_close_connection(cli)) {
2933                 correct = False;
2934         }
2935
2936         printf("finished negprot nowait test\n");
2937
2938         return correct;
2939 }
2940
2941 /* send smb negprot commands, not reading the response */
2942 static bool run_bad_nbt_session(int dummy)
2943 {
2944         static struct cli_state *cli;
2945
2946         printf("starting bad nbt session test\n");
2947
2948         if (!(cli = open_bad_nbt_connection())) {
2949                 return False;
2950         }
2951
2952         cli_shutdown(cli);
2953         printf("finished bad nbt session test\n");
2954         return true;
2955 }
2956
2957 /* send random IPC commands */
2958 static bool run_randomipc(int dummy)
2959 {
2960         char *rparam = NULL;
2961         char *rdata = NULL;
2962         unsigned int rdrcnt,rprcnt;
2963         char param[1024];
2964         int api, param_len, i;
2965         struct cli_state *cli;
2966         bool correct = True;
2967         int count = 50000;
2968
2969         printf("starting random ipc test\n");
2970
2971         if (!torture_open_connection(&cli, 0)) {
2972                 return False;
2973         }
2974
2975         for (i=0;i<count;i++) {
2976                 api = sys_random() % 500;
2977                 param_len = (sys_random() % 64);
2978
2979                 rand_buf(param, param_len);
2980
2981                 SSVAL(param,0,api); 
2982
2983                 cli_api(cli, 
2984                         param, param_len, 8,  
2985                         NULL, 0, BUFFER_SIZE, 
2986                         &rparam, &rprcnt,     
2987                         &rdata, &rdrcnt);
2988                 if (i % 100 == 0) {
2989                         printf("%d/%d\r", i,count);
2990                 }
2991         }
2992         printf("%d/%d\n", i, count);
2993
2994         if (!torture_close_connection(cli)) {
2995                 correct = False;
2996         }
2997
2998         printf("finished random ipc test\n");
2999
3000         return correct;
3001 }
3002
3003
3004
3005 static void browse_callback(const char *sname, uint32 stype, 
3006                             const char *comment, void *state)
3007 {
3008         printf("\t%20.20s %08x %s\n", sname, stype, comment);
3009 }
3010
3011
3012
3013 /*
3014   This test checks the browse list code
3015
3016 */
3017 static bool run_browsetest(int dummy)
3018 {
3019         static struct cli_state *cli;
3020         bool correct = True;
3021
3022         printf("starting browse test\n");
3023
3024         if (!torture_open_connection(&cli, 0)) {
3025                 return False;
3026         }
3027
3028         printf("domain list:\n");
3029         cli_NetServerEnum(cli, cli->server_domain, 
3030                           SV_TYPE_DOMAIN_ENUM,
3031                           browse_callback, NULL);
3032
3033         printf("machine list:\n");
3034         cli_NetServerEnum(cli, cli->server_domain, 
3035                           SV_TYPE_ALL,
3036                           browse_callback, NULL);
3037
3038         if (!torture_close_connection(cli)) {
3039                 correct = False;
3040         }
3041
3042         printf("browse test finished\n");
3043
3044         return correct;
3045
3046 }
3047
3048
3049 /*
3050   This checks how the getatr calls works
3051 */
3052 static bool run_attrtest(int dummy)
3053 {
3054         struct cli_state *cli;
3055         uint16_t fnum;
3056         time_t t, t2;
3057         const char *fname = "\\attrib123456789.tst";
3058         bool correct = True;
3059         NTSTATUS status;
3060
3061         printf("starting attrib test\n");
3062
3063         if (!torture_open_connection(&cli, 0)) {
3064                 return False;
3065         }
3066
3067         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3068         cli_open(cli, fname, 
3069                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3070         cli_close(cli, fnum);
3071
3072         status = cli_getatr(cli, fname, NULL, NULL, &t);
3073         if (!NT_STATUS_IS_OK(status)) {
3074                 printf("getatr failed (%s)\n", nt_errstr(status));
3075                 correct = False;
3076         }
3077
3078         if (abs(t - time(NULL)) > 60*60*24*10) {
3079                 printf("ERROR: SMBgetatr bug. time is %s",
3080                        ctime(&t));
3081                 t = time(NULL);
3082                 correct = True;
3083         }
3084
3085         t2 = t-60*60*24; /* 1 day ago */
3086
3087         status = cli_setatr(cli, fname, 0, t2);
3088         if (!NT_STATUS_IS_OK(status)) {
3089                 printf("setatr failed (%s)\n", nt_errstr(status));
3090                 correct = True;
3091         }
3092
3093         status = cli_getatr(cli, fname, NULL, NULL, &t);
3094         if (!NT_STATUS_IS_OK(status)) {
3095                 printf("getatr failed (%s)\n", nt_errstr(status));
3096                 correct = True;
3097         }
3098
3099         if (t != t2) {
3100                 printf("ERROR: getatr/setatr bug. times are\n%s",
3101                        ctime(&t));
3102                 printf("%s", ctime(&t2));
3103                 correct = True;
3104         }
3105
3106         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3107
3108         if (!torture_close_connection(cli)) {
3109                 correct = False;
3110         }
3111
3112         printf("attrib test finished\n");
3113
3114         return correct;
3115 }
3116
3117
3118 /*
3119   This checks a couple of trans2 calls
3120 */
3121 static bool run_trans2test(int dummy)
3122 {
3123         struct cli_state *cli;
3124         uint16_t fnum;
3125         SMB_OFF_T size;
3126         time_t c_time, a_time, m_time;
3127         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3128         const char *fname = "\\trans2.tst";
3129         const char *dname = "\\trans2";
3130         const char *fname2 = "\\trans2\\trans2.tst";
3131         char pname[1024];
3132         bool correct = True;
3133         NTSTATUS status;
3134         uint32_t fs_attr;
3135
3136         printf("starting trans2 test\n");
3137
3138         if (!torture_open_connection(&cli, 0)) {
3139                 return False;
3140         }
3141
3142         status = cli_get_fs_attr_info(cli, &fs_attr);
3143         if (!NT_STATUS_IS_OK(status)) {
3144                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3145                        nt_errstr(status));
3146                 correct = false;
3147         }
3148
3149         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3150         cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3151         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3152                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3153         if (!NT_STATUS_IS_OK(status)) {
3154                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3155                 correct = False;
3156         }
3157
3158         status = cli_qfilename(cli, fnum, pname, sizeof(pname));
3159         if (!NT_STATUS_IS_OK(status)) {
3160                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3161                 correct = False;
3162         }
3163
3164         if (strcmp(pname, fname)) {
3165                 printf("qfilename gave different name? [%s] [%s]\n",
3166                        fname, pname);
3167                 correct = False;
3168         }
3169
3170         cli_close(cli, fnum);
3171
3172         sleep(2);
3173
3174         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3175         status = cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3176                           &fnum);
3177         if (!NT_STATUS_IS_OK(status)) {
3178                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3179                 return False;
3180         }
3181         cli_close(cli, fnum);
3182
3183         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3184                                 NULL);
3185         if (!NT_STATUS_IS_OK(status)) {
3186                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3187                 correct = False;
3188         } else {
3189                 if (c_time != m_time) {
3190                         printf("create time=%s", ctime(&c_time));
3191                         printf("modify time=%s", ctime(&m_time));
3192                         printf("This system appears to have sticky create times\n");
3193                 }
3194                 if (a_time % (60*60) == 0) {
3195                         printf("access time=%s", ctime(&a_time));
3196                         printf("This system appears to set a midnight access time\n");
3197                         correct = False;
3198                 }
3199
3200                 if (abs(m_time - time(NULL)) > 60*60*24*7) {
3201                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3202                         correct = False;
3203                 }
3204         }
3205
3206
3207         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3208         cli_open(cli, fname, 
3209                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3210         cli_close(cli, fnum);
3211         status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3212                                 &m_time_ts, &size, NULL, NULL);
3213         if (!NT_STATUS_IS_OK(status)) {
3214                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3215                 correct = False;
3216         } else {
3217                 if (w_time_ts.tv_sec < 60*60*24*2) {
3218                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
3219                         printf("This system appears to set a initial 0 write time\n");
3220                         correct = False;
3221                 }
3222         }
3223
3224         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3225
3226
3227         /* check if the server updates the directory modification time
3228            when creating a new file */
3229         status = cli_mkdir(cli, dname);
3230         if (!NT_STATUS_IS_OK(status)) {
3231                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3232                 correct = False;
3233         }
3234         sleep(3);
3235         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3236                                 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3237         if (!NT_STATUS_IS_OK(status)) {
3238                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3239                 correct = False;
3240         }
3241
3242         cli_open(cli, fname2, 
3243                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3244         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3245         cli_close(cli, fnum);
3246         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3247                                 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3248         if (!NT_STATUS_IS_OK(status)) {
3249                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3250                 correct = False;
3251         } else {
3252                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3253                     == 0) {
3254                         printf("This system does not update directory modification times\n");
3255                         correct = False;
3256                 }
3257         }
3258         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3259         cli_rmdir(cli, dname);
3260
3261         if (!torture_close_connection(cli)) {
3262                 correct = False;
3263         }
3264
3265         printf("trans2 test finished\n");
3266
3267         return correct;
3268 }
3269
3270 /*
3271   This checks new W2K calls.
3272 */
3273
3274 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3275 {
3276         uint8_t *buf = NULL;
3277         uint32 len;
3278         NTSTATUS status;
3279
3280         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3281                                pcli->max_xmit, &buf, &len);
3282         if (!NT_STATUS_IS_OK(status)) {
3283                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3284                        nt_errstr(status));
3285         } else {
3286                 printf("qfileinfo: level %d, len = %u\n", level, len);
3287                 dump_data(0, (uint8 *)buf, len);
3288                 printf("\n");
3289         }
3290         TALLOC_FREE(buf);
3291         return status;
3292 }
3293
3294 static bool run_w2ktest(int dummy)
3295 {
3296         struct cli_state *cli;
3297         uint16_t fnum;
3298         const char *fname = "\\w2ktest\\w2k.tst";
3299         int level;
3300         bool correct = True;
3301
3302         printf("starting w2k test\n");
3303
3304         if (!torture_open_connection(&cli, 0)) {
3305                 return False;
3306         }
3307
3308         cli_open(cli, fname, 
3309                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
3310
3311         for (level = 1004; level < 1040; level++) {
3312                 new_trans(cli, fnum, level);
3313         }
3314
3315         cli_close(cli, fnum);
3316
3317         if (!torture_close_connection(cli)) {
3318                 correct = False;
3319         }
3320
3321         printf("w2k test finished\n");
3322
3323         return correct;
3324 }
3325
3326
3327 /*
3328   this is a harness for some oplock tests
3329  */
3330 static bool run_oplock1(int dummy)
3331 {
3332         struct cli_state *cli1;
3333         const char *fname = "\\lockt1.lck";
3334         uint16_t fnum1;
3335         bool correct = True;
3336         NTSTATUS status;
3337
3338         printf("starting oplock test 1\n");
3339
3340         if (!torture_open_connection(&cli1, 0)) {
3341                 return False;
3342         }
3343
3344         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3345
3346         cli_sockopt(cli1, sockops);
3347
3348         cli1->use_oplocks = True;
3349
3350         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3351                           &fnum1);
3352         if (!NT_STATUS_IS_OK(status)) {
3353                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3354                 return False;
3355         }
3356
3357         cli1->use_oplocks = False;
3358
3359         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3360         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3361
3362         status = cli_close(cli1, fnum1);
3363         if (!NT_STATUS_IS_OK(status)) {
3364                 printf("close2 failed (%s)\n", nt_errstr(status));
3365                 return False;
3366         }
3367
3368         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3369         if (!NT_STATUS_IS_OK(status)) {
3370                 printf("unlink failed (%s)\n", nt_errstr(status));
3371                 return False;
3372         }
3373
3374         if (!torture_close_connection(cli1)) {
3375                 correct = False;
3376         }
3377
3378         printf("finished oplock test 1\n");
3379
3380         return correct;
3381 }
3382
3383 static bool run_oplock2(int dummy)
3384 {
3385         struct cli_state *cli1, *cli2;
3386         const char *fname = "\\lockt2.lck";
3387         uint16_t fnum1, fnum2;
3388         int saved_use_oplocks = use_oplocks;
3389         char buf[4];
3390         bool correct = True;
3391         volatile bool *shared_correct;
3392         NTSTATUS status;
3393
3394         shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3395         *shared_correct = True;
3396
3397         use_level_II_oplocks = True;
3398         use_oplocks = True;
3399
3400         printf("starting oplock test 2\n");
3401
3402         if (!torture_open_connection(&cli1, 0)) {
3403                 use_level_II_oplocks = False;
3404                 use_oplocks = saved_use_oplocks;
3405                 return False;
3406         }
3407
3408         cli1->use_oplocks = True;
3409         cli1->use_level_II_oplocks = True;
3410
3411         if (!torture_open_connection(&cli2, 1)) {
3412                 use_level_II_oplocks = False;
3413                 use_oplocks = saved_use_oplocks;
3414                 return False;
3415         }
3416
3417         cli2->use_oplocks = True;
3418         cli2->use_level_II_oplocks = True;
3419
3420         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3421
3422         cli_sockopt(cli1, sockops);
3423         cli_sockopt(cli2, sockops);
3424
3425         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3426                           &fnum1);
3427         if (!NT_STATUS_IS_OK(status)) {
3428                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3429                 return False;
3430         }
3431
3432         /* Don't need the globals any more. */
3433         use_level_II_oplocks = False;
3434         use_oplocks = saved_use_oplocks;
3435
3436         if (fork() == 0) {
3437                 /* Child code */
3438                 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3439                 if (!NT_STATUS_IS_OK(status)) {
3440                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3441                         *shared_correct = False;
3442                         exit(0);
3443                 }
3444
3445                 sleep(2);
3446
3447                 status = cli_close(cli2, fnum2);
3448                 if (!NT_STATUS_IS_OK(status)) {
3449                         printf("close2 failed (%s)\n", nt_errstr(status));
3450                         *shared_correct = False;
3451                 }
3452
3453                 exit(0);
3454         }
3455
3456         sleep(2);
3457
3458         /* Ensure cli1 processes the break. Empty file should always return 0
3459          * bytes.  */
3460
3461         if (cli_read(cli1, fnum1, buf, 0, 4) != 0) {
3462                 printf("read on fnum1 failed (%s)\n", cli_errstr(cli1));
3463                 correct = False;
3464         }
3465
3466         /* Should now be at level II. */
3467         /* Test if sending a write locks causes a break to none. */
3468
3469         if (!cli_lock(cli1, fnum1, 0, 4, 0, READ_LOCK)) {
3470                 printf("lock failed (%s)\n", cli_errstr(cli1));
3471                 correct = False;
3472         }
3473
3474         cli_unlock(cli1, fnum1, 0, 4);
3475
3476         sleep(2);
3477
3478         if (!cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
3479                 printf("lock failed (%s)\n", cli_errstr(cli1));
3480                 correct = False;
3481         }
3482
3483         cli_unlock(cli1, fnum1, 0, 4);
3484
3485         sleep(2);
3486
3487         cli_read(cli1, fnum1, buf, 0, 4);
3488
3489         status = cli_close(cli1, fnum1);
3490         if (!NT_STATUS_IS_OK(status)) {
3491                 printf("close1 failed (%s)\n", nt_errstr(status));
3492                 correct = False;
3493         }
3494
3495         sleep(4);
3496
3497         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3498         if (!NT_STATUS_IS_OK(status)) {
3499                 printf("unlink failed (%s)\n", nt_errstr(status));
3500                 correct = False;
3501         }
3502
3503         if (!torture_close_connection(cli1)) {
3504                 correct = False;
3505         }
3506
3507         if (!*shared_correct) {
3508                 correct = False;
3509         }
3510
3511         printf("finished oplock test 2\n");
3512
3513         return correct;
3514 }
3515
3516 /* handler for oplock 3 tests */
3517 static NTSTATUS oplock3_handler(struct cli_state *cli, uint16_t fnum, unsigned char level)
3518 {
3519         printf("got oplock break fnum=%d level=%d\n",
3520                fnum, level);
3521         return cli_oplock_ack(cli, fnum, level);
3522 }
3523
3524 static bool run_oplock3(int dummy)
3525 {
3526         struct cli_state *cli;
3527         const char *fname = "\\oplockt3.dat";
3528         uint16_t fnum;
3529         char buf[4] = "abcd";
3530         bool correct = True;
3531         volatile bool *shared_correct;
3532
3533         shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3534         *shared_correct = True;
3535
3536         printf("starting oplock test 3\n");
3537
3538         if (fork() == 0) {
3539                 /* Child code */
3540                 use_oplocks = True;
3541                 use_level_II_oplocks = True;
3542                 if (!torture_open_connection(&cli, 0)) {
3543                         *shared_correct = False;
3544                         exit(0);
3545                 } 
3546                 sleep(2);
3547                 /* try to trigger a oplock break in parent */
3548                 cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum);
3549                 cli_writeall(cli, fnum, 0, (uint8_t *)buf, 0, 4, NULL);
3550                 exit(0);
3551         }
3552
3553         /* parent code */
3554         use_oplocks = True;
3555         use_level_II_oplocks = True;
3556         if (!torture_open_connection(&cli, 1)) { /* other is forked */
3557                 return False;
3558         }
3559         cli_oplock_handler(cli, oplock3_handler);
3560         cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum);
3561         cli_writeall(cli, fnum, 0, (uint8_t *)buf, 0, 4, NULL);
3562         cli_close(cli, fnum);
3563         cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum);
3564         cli->timeout = 20000;
3565         cli_receive_smb(cli);
3566         printf("finished oplock test 3\n");
3567
3568         return (correct && *shared_correct);
3569
3570 /* What are we looking for here?  What's sucess and what's FAILURE? */
3571 }
3572
3573 /* handler for oplock 4 tests */
3574 bool *oplock4_shared_correct;
3575
3576 static NTSTATUS oplock4_handler(struct cli_state *cli, uint16_t fnum, unsigned char level)
3577 {
3578         printf("got oplock break fnum=%d level=%d\n",
3579                fnum, level);
3580         *oplock4_shared_correct = true;
3581         cli_oplock_ack(cli, fnum, level);
3582         return NT_STATUS_UNSUCCESSFUL; /* Cause cli_receive_smb to return. */
3583 }
3584
3585 static bool run_oplock4(int dummy)
3586 {
3587         struct cli_state *cli1, *cli2;
3588         const char *fname = "\\lockt4.lck";
3589         const char *fname_ln = "\\lockt4_ln.lck";
3590         uint16_t fnum1, fnum2;
3591         int saved_use_oplocks = use_oplocks;
3592         NTSTATUS status;
3593         bool correct = true;
3594
3595         oplock4_shared_correct = (bool *)shm_setup(sizeof(bool));
3596         *oplock4_shared_correct = false;
3597
3598         printf("starting oplock test 4\n");
3599
3600         if (!torture_open_connection(&cli1, 0)) {
3601                 use_level_II_oplocks = false;
3602                 use_oplocks = saved_use_oplocks;
3603                 return false;
3604         }
3605
3606         if (!torture_open_connection(&cli2, 1)) {
3607                 use_level_II_oplocks = false;
3608                 use_oplocks = saved_use_oplocks;
3609                 return false;
3610         }
3611
3612         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3613         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3614
3615         cli_sockopt(cli1, sockops);
3616         cli_sockopt(cli2, sockops);
3617
3618         /* Create the file. */
3619         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3620                           &fnum1);
3621         if (!NT_STATUS_IS_OK(status)) {
3622                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3623                 return false;
3624         }
3625
3626         status = cli_close(cli1, fnum1);
3627         if (!NT_STATUS_IS_OK(status)) {
3628                 printf("close1 failed (%s)\n", nt_errstr(status));
3629                 return false;
3630         }
3631
3632         /* Now create a hardlink. */
3633         status = cli_nt_hardlink(cli1, fname, fname_ln);
3634         if (!NT_STATUS_IS_OK(status)) {
3635                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3636                 return false;
3637         }
3638
3639         /* Prove that opening hardlinks cause deny modes to conflict. */
3640         status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3641         if (!NT_STATUS_IS_OK(status)) {
3642                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3643                 return false;
3644         }
3645
3646         status = cli_open(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3647         if (NT_STATUS_IS_OK(status)) {
3648                 printf("open of %s succeeded - should fail with sharing violation.\n",
3649                         fname_ln);
3650                 return false;
3651         }
3652
3653         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3654                 printf("open of %s should fail with sharing violation. Got %s\n",
3655                         fname_ln, nt_errstr(status));
3656                 return false;
3657         }
3658
3659         status = cli_close(cli1, fnum1);
3660         if (!NT_STATUS_IS_OK(status)) {
3661                 printf("close1 failed (%s)\n", nt_errstr(status));
3662                 return false;
3663         }
3664
3665         cli1->use_oplocks = true;
3666         cli1->use_level_II_oplocks = true;
3667
3668         cli2->use_oplocks = true;
3669         cli2->use_level_II_oplocks = true;
3670
3671         cli_oplock_handler(cli1, oplock4_handler);
3672
3673         status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3674         if (!NT_STATUS_IS_OK(status)) {
3675                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3676                 return false;
3677         }
3678
3679         if (fork() == 0) {
3680                 /* Child code */
3681                 status = cli_open(cli2, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3682                 if (!NT_STATUS_IS_OK(status)) {
3683                         printf("open of %s failed (%s)\n", fname_ln, nt_errstr(status));
3684                         *oplock4_shared_correct = false;
3685                         exit(0);
3686                 }
3687
3688                 status = cli_close(cli2, fnum2);
3689                 if (!NT_STATUS_IS_OK(status)) {
3690                         printf("close2 failed (%s)\n", nt_errstr(status));
3691                         *oplock4_shared_correct = false;
3692                 }
3693
3694                 exit(0);
3695         }
3696
3697         sleep(2);
3698
3699         /* Process the oplock break. */
3700         cli_receive_smb(cli1);
3701
3702         status = cli_close(cli1, fnum1);
3703         if (!NT_STATUS_IS_OK(status)) {
3704                 printf("close1 failed (%s)\n", nt_errstr(status));
3705                 correct = false;
3706         }
3707
3708         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3709         if (!NT_STATUS_IS_OK(status)) {
3710                 printf("unlink failed (%s)\n", nt_errstr(status));
3711                 correct = false;
3712         }
3713
3714         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3715         if (!NT_STATUS_IS_OK(status)) {
3716                 printf("unlink failed (%s)\n", nt_errstr(status));
3717                 correct = false;
3718         }
3719
3720         if (!torture_close_connection(cli1)) {
3721                 correct = false;
3722         }
3723
3724         if (!*oplock4_shared_correct) {
3725                 correct = false;
3726         }
3727
3728         printf("finished oplock test 4\n");
3729
3730         return correct;
3731 }
3732
3733
3734 /*
3735   Test delete on close semantics.
3736  */
3737 static bool run_deletetest(int dummy)
3738 {
3739         struct cli_state *cli1 = NULL;
3740         struct cli_state *cli2 = NULL;
3741         const char *fname = "\\delete.file";
3742         uint16_t fnum1 = (uint16_t)-1;
3743         uint16_t fnum2 = (uint16_t)-1;
3744         bool correct = True;
3745         NTSTATUS status;
3746
3747         printf("starting delete test\n");
3748
3749         if (!torture_open_connection(&cli1, 0)) {
3750                 return False;
3751         }
3752
3753         cli_sockopt(cli1, sockops);
3754
3755         /* Test 1 - this should delete the file on close. */
3756
3757         cli_setatr(cli1, fname, 0, 0);
3758         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3759
3760         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3761                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3762                               FILE_DELETE_ON_CLOSE, 0, &fnum1);
3763         if (!NT_STATUS_IS_OK(status)) {
3764                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3765                 correct = False;
3766                 goto fail;
3767         }
3768
3769         status = cli_close(cli1, fnum1);
3770         if (!NT_STATUS_IS_OK(status)) {
3771                 printf("[1] close failed (%s)\n", nt_errstr(status));
3772                 correct = False;
3773                 goto fail;
3774         }
3775
3776         if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1))) {
3777                 printf("[1] open of %s succeeded (should fail)\n", fname);
3778                 correct = False;
3779                 goto fail;
3780         }
3781
3782         printf("first delete on close test succeeded.\n");
3783
3784         /* Test 2 - this should delete the file on close. */
3785
3786         cli_setatr(cli1, fname, 0, 0);
3787         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3788
3789         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3790                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3791                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
3792         if (!NT_STATUS_IS_OK(status)) {
3793                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3794                 correct = False;
3795                 goto fail;
3796         }
3797
3798         status = cli_nt_delete_on_close(cli1, fnum1, true);
3799         if (!NT_STATUS_IS_OK(status)) {
3800                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3801                 correct = False;
3802                 goto fail;
3803         }
3804
3805         status = cli_close(cli1, fnum1);
3806         if (!NT_STATUS_IS_OK(status)) {
3807                 printf("[2] close failed (%s)\n", nt_errstr(status));
3808                 correct = False;
3809                 goto fail;
3810         }
3811
3812         if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3813                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3814                 status = cli_close(cli1, fnum1);
3815                 if (!NT_STATUS_IS_OK(status)) {
3816                         printf("[2] close failed (%s)\n", nt_errstr(status));
3817                         correct = False;
3818                         goto fail;
3819                 }
3820                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3821         } else
3822                 printf("second delete on close test succeeded.\n");
3823
3824         /* Test 3 - ... */
3825         cli_setatr(cli1, fname, 0, 0);
3826         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3827
3828         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3829                               FILE_ATTRIBUTE_NORMAL,
3830                               FILE_SHARE_READ|FILE_SHARE_WRITE,
3831                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
3832         if (!NT_STATUS_IS_OK(status)) {
3833                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
3834                 correct = False;
3835                 goto fail;
3836         }
3837
3838         /* This should fail with a sharing violation - open for delete is only compatible
3839            with SHARE_DELETE. */
3840
3841         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3842                         FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, &fnum2))) {
3843                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
3844                 correct = False;
3845                 goto fail;
3846         }
3847
3848         /* This should succeed. */
3849         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3850                              FILE_ATTRIBUTE_NORMAL,
3851                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3852                              FILE_OPEN, 0, 0, &fnum2);
3853         if (!NT_STATUS_IS_OK(status)) {
3854                 printf("[3] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
3855                 correct = False;
3856                 goto fail;
3857         }
3858
3859         status = cli_nt_delete_on_close(cli1, fnum1, true);
3860         if (!NT_STATUS_IS_OK(status)) {
3861                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
3862                 correct = False;
3863                 goto fail;
3864         }
3865
3866         status = cli_close(cli1, fnum1);
3867         if (!NT_STATUS_IS_OK(status)) {
3868                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
3869                 correct = False;
3870                 goto fail;
3871         }
3872
3873         status = cli_close(cli1, fnum2);
3874         if (!NT_STATUS_IS_OK(status)) {
3875                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
3876                 correct = False;
3877                 goto fail;
3878         }
3879
3880         /* This should fail - file should no longer be there. */
3881
3882         if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3883                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
3884                 status = cli_close(cli1, fnum1);
3885                 if (!NT_STATUS_IS_OK(status)) {
3886                         printf("[3] close failed (%s)\n", nt_errstr(status));
3887                 }
3888                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3889                 correct = False;
3890                 goto fail;
3891         } else
3892                 printf("third delete on close test succeeded.\n");
3893
3894         /* Test 4 ... */
3895         cli_setatr(cli1, fname, 0, 0);
3896         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3897
3898         status = cli_ntcreate(cli1, fname, 0,
3899                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
3900                               FILE_ATTRIBUTE_NORMAL,
3901                               FILE_SHARE_READ|FILE_SHARE_WRITE,
3902                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
3903         if (!NT_STATUS_IS_OK(status)) {
3904                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
3905                 correct = False;
3906                 goto fail;
3907         }
3908
3909         /* This should succeed. */
3910         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3911                              FILE_ATTRIBUTE_NORMAL,
3912                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3913                              FILE_OPEN, 0, 0, &fnum2);
3914         if (!NT_STATUS_IS_OK(status)) {
3915                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
3916                 correct = False;
3917                 goto fail;
3918         }
3919
3920         status = cli_close(cli1, fnum2);
3921         if (!NT_STATUS_IS_OK(status)) {
3922                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
3923                 correct = False;
3924                 goto fail;
3925         }
3926
3927         status = cli_nt_delete_on_close(cli1, fnum1, true);
3928         if (!NT_STATUS_IS_OK(status)) {
3929                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
3930                 correct = False;
3931                 goto fail;
3932         }
3933
3934         /* This should fail - no more opens once delete on close set. */
3935         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3936                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3937                                    FILE_OPEN, 0, 0, &fnum2))) {
3938                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
3939                 correct = False;
3940                 goto fail;
3941         } else
3942                 printf("fourth delete on close test succeeded.\n");
3943
3944         status = cli_close(cli1, fnum1);
3945         if (!NT_STATUS_IS_OK(status)) {
3946                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
3947                 correct = False;
3948                 goto fail;
3949         }
3950
3951         /* Test 5 ... */
3952         cli_setatr(cli1, fname, 0, 0);
3953         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3954
3955         status = cli_open(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
3956         if (!NT_STATUS_IS_OK(status)) {
3957                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
3958                 correct = False;
3959                 goto fail;
3960         }
3961
3962         /* This should fail - only allowed on NT opens with DELETE access. */
3963
3964         if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3965                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
3966                 correct = False;
3967                 goto fail;
3968         }
3969
3970         status = cli_close(cli1, fnum1);
3971         if (!NT_STATUS_IS_OK(status)) {
3972                 printf("[5] close - 2 failed (%s)\n", nt_errstr(status));
3973                 correct = False;
3974                 goto fail;
3975         }
3976
3977         printf("fifth delete on close test succeeded.\n");
3978
3979         /* Test 6 ... */
3980         cli_setatr(cli1, fname, 0, 0);
3981         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3982
3983         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
3984                              FILE_ATTRIBUTE_NORMAL,
3985                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3986                              FILE_OVERWRITE_IF, 0, 0, &fnum1);
3987         if (!NT_STATUS_IS_OK(status)) {
3988                 printf("[6] open of %s failed (%s)\n", fname,
3989                        nt_errstr(status));
3990                 correct = False;
3991                 goto fail;
3992         }
3993
3994         /* This should fail - only allowed on NT opens with DELETE access. */
3995
3996         if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3997                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
3998                 correct = False;
3999                 goto fail;
4000         }
4001
4002         status = cli_close(cli1, fnum1);
4003         if (!NT_STATUS_IS_OK(status)) {
4004                 printf("[6] close - 2 failed (%s)\n", nt_errstr(status));
4005                 correct = False;
4006                 goto fail;
4007         }
4008
4009         printf("sixth delete on close test succeeded.\n");
4010
4011         /* Test 7 ... */
4012         cli_setatr(cli1, fname, 0, 0);
4013         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4014
4015         status = cli_ntcreate(cli1, fname, 0,
4016                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4017                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4018                               0, 0, &fnum1);
4019         if (!NT_STATUS_IS_OK(status)) {
4020                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4021                 correct = False;
4022                 goto fail;
4023         }
4024
4025         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4026                 printf("[7] setting delete_on_close on file failed !\n");
4027                 correct = False;
4028                 goto fail;
4029         }
4030
4031         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, false))) {
4032                 printf("[7] unsetting delete_on_close on file failed !\n");
4033                 correct = False;
4034                 goto fail;
4035         }
4036
4037         status = cli_close(cli1, fnum1);
4038         if (!NT_STATUS_IS_OK(status)) {
4039                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4040                 correct = False;
4041                 goto fail;
4042         }
4043
4044         /* This next open should succeed - we reset the flag. */
4045         status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4046         if (!NT_STATUS_IS_OK(status)) {
4047                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4048                 correct = False;
4049                 goto fail;
4050         }
4051
4052         status = cli_close(cli1, fnum1);
4053         if (!NT_STATUS_IS_OK(status)) {
4054                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4055                 correct = False;
4056                 goto fail;
4057         }
4058
4059         printf("seventh delete on close test succeeded.\n");
4060
4061         /* Test 7 ... */
4062         cli_setatr(cli1, fname, 0, 0);
4063         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4064
4065         if (!torture_open_connection(&cli2, 1)) {
4066                 printf("[8] failed to open second connection.\n");
4067                 correct = False;
4068                 goto fail;
4069         }
4070
4071         cli_sockopt(cli1, sockops);
4072
4073         status = cli_ntcreate(cli1, fname, 0,
4074                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4075                              FILE_ATTRIBUTE_NORMAL,
4076                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4077                              FILE_OVERWRITE_IF, 0, 0, &fnum1);
4078         if (!NT_STATUS_IS_OK(status)) {
4079                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4080                 correct = False;
4081                 goto fail;
4082         }
4083
4084         status = cli_ntcreate(cli2, fname, 0,
4085                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4086                              FILE_ATTRIBUTE_NORMAL,
4087                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4088                              FILE_OPEN, 0, 0, &fnum2);
4089         if (!NT_STATUS_IS_OK(status)) {
4090                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4091                 correct = False;
4092                 goto fail;
4093         }
4094
4095         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4096                 printf("[8] setting delete_on_close on file failed !\n");
4097                 correct = False;
4098                 goto fail;
4099         }
4100
4101         status = cli_close(cli1, fnum1);
4102         if (!NT_STATUS_IS_OK(status)) {
4103                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4104                 correct = False;
4105                 goto fail;
4106         }
4107
4108         status = cli_close(cli2, fnum2);
4109         if (!NT_STATUS_IS_OK(status)) {
4110                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4111                 correct = False;
4112                 goto fail;
4113         }
4114
4115         /* This should fail.. */
4116         status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4117         if (NT_STATUS_IS_OK(status)) {
4118                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4119                 goto fail;
4120                 correct = False;
4121         } else
4122                 printf("eighth delete on close test succeeded.\n");
4123
4124         /* This should fail - we need to set DELETE_ACCESS. */
4125         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,FILE_READ_DATA|FILE_WRITE_DATA,
4126                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
4127                 printf("[9] open of %s succeeded should have failed!\n", fname);
4128                 correct = False;
4129                 goto fail;
4130         }
4131
4132         printf("ninth delete on close test succeeded.\n");
4133
4134         status = cli_ntcreate(cli1, fname, 0,
4135                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4136                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4137                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4138                              0, &fnum1);
4139         if (!NT_STATUS_IS_OK(status)) {
4140                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4141                 correct = False;
4142                 goto fail;
4143         }
4144
4145         /* This should delete the file. */
4146         status = cli_close(cli1, fnum1);
4147         if (!NT_STATUS_IS_OK(status)) {
4148                 printf("[10] close failed (%s)\n", nt_errstr(status));
4149                 correct = False;
4150                 goto fail;
4151         }
4152
4153         /* This should fail.. */
4154         if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4155                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4156                 goto fail;
4157                 correct = False;
4158         } else
4159                 printf("tenth delete on close test succeeded.\n");
4160
4161         cli_setatr(cli1, fname, 0, 0);
4162         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4163
4164         /* What error do we get when attempting to open a read-only file with
4165            delete access ? */
4166
4167         /* Create a readonly file. */
4168         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4169                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4170                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4171         if (!NT_STATUS_IS_OK(status)) {
4172                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4173                 correct = False;
4174                 goto fail;
4175         }
4176
4177         status = cli_close(cli1, fnum1);
4178         if (!NT_STATUS_IS_OK(status)) {
4179                 printf("[11] close failed (%s)\n", nt_errstr(status));
4180                 correct = False;
4181                 goto fail;
4182         }
4183
4184         /* Now try open for delete access. */
4185         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4186                                    0, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4187                                    FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4188                 printf("[11] open of %s succeeded should have been denied with ACCESS_DENIED!\n", fname);
4189                 cli_close(cli1, fnum1);
4190                 goto fail;
4191                 correct = False;
4192         } else {
4193                 NTSTATUS nterr = cli_nt_error(cli1);
4194                 if (!NT_STATUS_EQUAL(nterr,NT_STATUS_ACCESS_DENIED)) {
4195                         printf("[11] open of %s should have been denied with ACCESS_DENIED! Got error %s\n", fname, nt_errstr(nterr));
4196                         goto fail;
4197                         correct = False;
4198                 } else {
4199                         printf("eleventh delete on close test succeeded.\n");
4200                 }
4201         }
4202
4203         printf("finished delete test\n");
4204
4205   fail:
4206         /* FIXME: This will crash if we aborted before cli2 got
4207          * intialized, because these functions don't handle
4208          * uninitialized connections. */
4209
4210         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4211         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4212         cli_setatr(cli1, fname, 0, 0);
4213         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4214
4215         if (cli1 && !torture_close_connection(cli1)) {
4216                 correct = False;
4217         }
4218         if (cli2 && !torture_close_connection(cli2)) {
4219                 correct = False;
4220         }
4221         return correct;
4222 }
4223
4224 static bool run_deletetest_ln(int dummy)
4225 {
4226         struct cli_state *cli;
4227         const char *fname = "\\delete1";
4228         const char *fname_ln = "\\delete1_ln";
4229         uint16_t fnum;
4230         uint16_t fnum1;
4231         NTSTATUS status;
4232         bool correct = true;
4233         time_t t;
4234
4235         printf("starting deletetest-ln\n");
4236
4237         if (!torture_open_connection(&cli, 0)) {
4238                 return false;
4239         }
4240
4241         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4242         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4243
4244         cli_sockopt(cli, sockops);
4245
4246         /* Create the file. */
4247         status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4248         if (!NT_STATUS_IS_OK(status)) {
4249                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4250                 return false;
4251         }
4252
4253         status = cli_close(cli, fnum);
4254         if (!NT_STATUS_IS_OK(status)) {
4255                 printf("close1 failed (%s)\n", nt_errstr(status));
4256                 return false;
4257         }
4258
4259         /* Now create a hardlink. */
4260         status = cli_nt_hardlink(cli, fname, fname_ln);
4261         if (!NT_STATUS_IS_OK(status)) {
4262                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4263                 return false;
4264         }
4265
4266         /* Open the original file. */
4267         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4268                         FILE_ATTRIBUTE_NORMAL,
4269                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4270                         FILE_OPEN_IF, 0, 0, &fnum);
4271         if (!NT_STATUS_IS_OK(status)) {
4272                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4273                 return false;
4274         }
4275
4276         /* Unlink the hard link path. */
4277         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4278                         FILE_ATTRIBUTE_NORMAL,
4279                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4280                         FILE_OPEN_IF, 0, 0, &fnum1);
4281         if (!NT_STATUS_IS_OK(status)) {
4282                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4283                 return false;
4284         }
4285         status = cli_nt_delete_on_close(cli, fnum1, true);
4286         if (!NT_STATUS_IS_OK(status)) {
4287                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4288                         __location__, fname_ln, nt_errstr(status));
4289                 return false;
4290         }
4291
4292         status = cli_close(cli, fnum1);
4293         if (!NT_STATUS_IS_OK(status)) {
4294                 printf("close %s failed (%s)\n",
4295                         fname_ln, nt_errstr(status));
4296                 return false;
4297         }
4298
4299         status = cli_close(cli, fnum);
4300         if (!NT_STATUS_IS_OK(status)) {
4301                 printf("close %s failed (%s)\n",
4302                         fname, nt_errstr(status));
4303                 return false;
4304         }
4305
4306         /* Ensure the original file is still there. */
4307         status = cli_getatr(cli, fname, NULL, NULL, &t);
4308         if (!NT_STATUS_IS_OK(status)) {
4309                 printf("%s getatr on file %s failed (%s)\n",
4310                         __location__,
4311                         fname,
4312                         nt_errstr(status));
4313                 correct = False;
4314         }
4315
4316         /* Ensure the link path is gone. */
4317         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4318         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4319                 printf("%s, getatr for file %s returned wrong error code %s "
4320                         "- should have been deleted\n",
4321                         __location__,
4322                         fname_ln, nt_errstr(status));
4323                 correct = False;
4324         }
4325
4326         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4327         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4328
4329         if (!torture_close_connection(cli)) {
4330                 correct = false;
4331         }
4332
4333         printf("finished deletetest-ln\n");
4334
4335         return correct;
4336 }
4337
4338 /*
4339   print out server properties
4340  */
4341 static bool run_properties(int dummy)
4342 {
4343         struct cli_state *cli;
4344         bool correct = True;
4345
4346         printf("starting properties test\n");
4347
4348         ZERO_STRUCT(cli);
4349
4350         if (!torture_open_connection(&cli, 0)) {
4351                 return False;
4352         }
4353
4354         cli_sockopt(cli, sockops);
4355
4356         d_printf("Capabilities 0x%08x\n", cli->capabilities);
4357
4358         if (!torture_close_connection(cli)) {
4359                 correct = False;
4360         }
4361
4362         return correct;
4363 }
4364
4365
4366
4367 /* FIRST_DESIRED_ACCESS   0xf019f */
4368 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4369                                FILE_READ_EA|                           /* 0xf */ \
4370                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
4371                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
4372                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
4373                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
4374 /* SECOND_DESIRED_ACCESS  0xe0080 */
4375 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4376                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4377                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
4378
4379 #if 0
4380 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4381                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4382                                FILE_READ_DATA|\
4383                                WRITE_OWNER_ACCESS                      /* */
4384 #endif
4385
4386 /*
4387   Test ntcreate calls made by xcopy
4388  */
4389 static bool run_xcopy(int dummy)
4390 {
4391         static struct cli_state *cli1;
4392         const char *fname = "\\test.txt";
4393         bool correct = True;
4394         uint16_t fnum1, fnum2;
4395         NTSTATUS status;
4396
4397         printf("starting xcopy test\n");
4398
4399         if (!torture_open_connection(&cli1, 0)) {
4400                 return False;
4401         }
4402
4403         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4404                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4405                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1);
4406         if (!NT_STATUS_IS_OK(status)) {
4407                 printf("First open failed - %s\n", nt_errstr(status));
4408                 return False;
4409         }
4410
4411         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4412                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4413                              FILE_OPEN, 0x200000, 0, &fnum2);
4414         if (!NT_STATUS_IS_OK(status)) {
4415                 printf("second open failed - %s\n", nt_errstr(status));
4416                 return False;
4417         }
4418
4419         if (!torture_close_connection(cli1)) {
4420                 correct = False;
4421         }
4422
4423         return correct;
4424 }
4425
4426 /*
4427   Test rename on files open with share delete and no share delete.
4428  */
4429 static bool run_rename(int dummy)
4430 {
4431         static struct cli_state *cli1;
4432         const char *fname = "\\test.txt";
4433         const char *fname1 = "\\test1.txt";
4434         bool correct = True;
4435         uint16_t fnum1;
4436         uint16_t attr;
4437         NTSTATUS status;
4438
4439         printf("starting rename test\n");
4440
4441         if (!torture_open_connection(&cli1, 0)) {
4442                 return False;
4443         }
4444
4445         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4446         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4447
4448         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4449                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4450                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4451         if (!NT_STATUS_IS_OK(status)) {
4452                 printf("First open failed - %s\n", nt_errstr(status));
4453                 return False;
4454         }
4455
4456         status = cli_rename(cli1, fname, fname1);
4457         if (!NT_STATUS_IS_OK(status)) {
4458                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4459         } else {
4460                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4461                 correct = False;
4462         }
4463
4464         status = cli_close(cli1, fnum1);
4465         if (!NT_STATUS_IS_OK(status)) {
4466                 printf("close - 1 failed (%s)\n", nt_errstr(status));
4467                 return False;
4468         }
4469
4470         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4471         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4472         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4473 #if 0
4474                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
4475 #else
4476                               FILE_SHARE_DELETE|FILE_SHARE_READ,
4477 #endif
4478                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4479         if (!NT_STATUS_IS_OK(status)) {
4480                 printf("Second open failed - %s\n", nt_errstr(status));
4481                 return False;
4482         }
4483
4484         status = cli_rename(cli1, fname, fname1);
4485         if (!NT_STATUS_IS_OK(status)) {
4486                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4487                 correct = False;
4488         } else {
4489                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4490         }
4491
4492         status = cli_close(cli1, fnum1);
4493         if (!NT_STATUS_IS_OK(status)) {
4494                 printf("close - 2 failed (%s)\n", nt_errstr(status));
4495                 return False;
4496         }
4497
4498         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4499         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4500
4501         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4502                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4503                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4504         if (!NT_STATUS_IS_OK(status)) {
4505                 printf("Third open failed - %s\n", nt_errstr(status));
4506                 return False;
4507         }
4508
4509
4510 #if 0
4511   {
4512         uint16_t fnum2;
4513
4514         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4515                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4516                 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4517                 return False;
4518         }
4519         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4520                 printf("[8] setting delete_on_close on file failed !\n");
4521                 return False;
4522         }
4523
4524         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4525                 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4526                 return False;
4527         }
4528   }
4529 #endif
4530
4531         status = cli_rename(cli1, fname, fname1);
4532         if (!NT_STATUS_IS_OK(status)) {
4533                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4534                 correct = False;
4535         } else {
4536                 printf("Third rename succeeded (SHARE_NONE)\n");
4537         }
4538
4539         status = cli_close(cli1, fnum1);
4540         if (!NT_STATUS_IS_OK(status)) {
4541                 printf("close - 3 failed (%s)\n", nt_errstr(status));
4542                 return False;
4543         }
4544
4545         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4546         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4547
4548         /*----*/
4549
4550         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4551                               FILE_ATTRIBUTE_NORMAL,
4552                               FILE_SHARE_READ | FILE_SHARE_WRITE,
4553                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4554         if (!NT_STATUS_IS_OK(status)) {
4555                 printf("Fourth open failed - %s\n", nt_errstr(status));
4556                 return False;
4557         }
4558
4559         status = cli_rename(cli1, fname, fname1);
4560         if (!NT_STATUS_IS_OK(status)) {
4561                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4562         } else {
4563                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4564                 correct = False;
4565         }
4566
4567         status = cli_close(cli1, fnum1);
4568         if (!NT_STATUS_IS_OK(status)) {
4569                 printf("close - 4 failed (%s)\n", nt_errstr(status));
4570                 return False;
4571         }
4572
4573         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4574         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4575
4576         /*--*/
4577
4578         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4579                          FILE_ATTRIBUTE_NORMAL,
4580                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4581                          FILE_OVERWRITE_IF, 0, 0, &fnum1);
4582         if (!NT_STATUS_IS_OK(status)) {
4583                 printf("Fifth open failed - %s\n", nt_errstr(status));
4584                 return False;
4585         }
4586
4587         status = cli_rename(cli1, fname, fname1);
4588         if (!NT_STATUS_IS_OK(status)) {
4589                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4590                 correct = False;
4591         } else {
4592                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4593         }
4594
4595         /*
4596          * Now check if the first name still exists ...
4597          */
4598
4599         /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4600                                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4601           printf("Opening original file after rename of open file fails: %s\n",
4602               cli_errstr(cli1));
4603         }
4604         else {
4605           printf("Opening original file after rename of open file works ...\n");
4606           (void)cli_close(cli1, fnum2);
4607           } */
4608
4609         /*--*/
4610         status = cli_close(cli1, fnum1);
4611         if (!NT_STATUS_IS_OK(status)) {
4612                 printf("close - 5 failed (%s)\n", nt_errstr(status));
4613                 return False;
4614         }
4615
4616         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4617         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4618         if (!NT_STATUS_IS_OK(status)) {
4619                 printf("getatr on file %s failed - %s ! \n",
4620                         fname1, nt_errstr(status));
4621                 correct = False;
4622         } else {
4623                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4624                         printf("Renamed file %s has wrong attr 0x%x "
4625                                 "(should be 0x%x)\n",
4626                                 fname1,
4627                                 attr,
4628                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4629                         correct = False;
4630                 } else {
4631                         printf("Renamed file %s has archive bit set\n", fname1);
4632                 }
4633         }
4634
4635         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4636         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4637
4638         if (!torture_close_connection(cli1)) {
4639                 correct = False;
4640         }
4641
4642         return correct;
4643 }
4644
4645 static bool run_pipe_number(int dummy)
4646 {
4647         struct cli_state *cli1;
4648         const char *pipe_name = "\\SPOOLSS";
4649         uint16_t fnum;
4650         int num_pipes = 0;
4651         NTSTATUS status;
4652
4653         printf("starting pipenumber test\n");
4654         if (!torture_open_connection(&cli1, 0)) {
4655                 return False;
4656         }
4657
4658         cli_sockopt(cli1, sockops);
4659         while(1) {
4660                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
4661                                       FILE_ATTRIBUTE_NORMAL,
4662                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
4663                                       FILE_OPEN_IF, 0, 0, &fnum);
4664                 if (!NT_STATUS_IS_OK(status)) {
4665                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
4666                         break;
4667                 }
4668                 num_pipes++;
4669                 printf("\r%6d", num_pipes);
4670         }
4671
4672         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4673         torture_close_connection(cli1);
4674         return True;
4675 }
4676
4677 /*
4678   Test open mode returns on read-only files.
4679  */
4680 static bool run_opentest(int dummy)
4681 {
4682         static struct cli_state *cli1;
4683         static struct cli_state *cli2;
4684         const char *fname = "\\readonly.file";
4685         uint16_t fnum1, fnum2;
4686         char buf[20];
4687         SMB_OFF_T fsize;
4688         bool correct = True;
4689         char *tmp_path;
4690         NTSTATUS status;
4691
4692         printf("starting open test\n");
4693
4694         if (!torture_open_connection(&cli1, 0)) {
4695                 return False;
4696         }
4697
4698         cli_setatr(cli1, fname, 0, 0);
4699         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4700
4701         cli_sockopt(cli1, sockops);
4702
4703         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4704         if (!NT_STATUS_IS_OK(status)) {
4705                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4706                 return False;
4707         }
4708
4709         status = cli_close(cli1, fnum1);
4710         if (!NT_STATUS_IS_OK(status)) {
4711                 printf("close2 failed (%s)\n", nt_errstr(status));
4712                 return False;
4713         }
4714
4715         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
4716         if (!NT_STATUS_IS_OK(status)) {
4717                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
4718                 return False;
4719         }
4720
4721         status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4722         if (!NT_STATUS_IS_OK(status)) {
4723                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4724                 return False;
4725         }
4726
4727         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4728         cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4729
4730         if (check_error(__LINE__, cli1, ERRDOS, ERRnoaccess, 
4731                         NT_STATUS_ACCESS_DENIED)) {
4732                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4733         }
4734
4735         printf("finished open test 1\n");
4736
4737         cli_close(cli1, fnum1);
4738
4739         /* Now try not readonly and ensure ERRbadshare is returned. */
4740
4741         cli_setatr(cli1, fname, 0, 0);
4742
4743         status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4744         if (!NT_STATUS_IS_OK(status)) {
4745                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4746                 return False;
4747         }
4748
4749         /* This will fail - but the error should be ERRshare. */
4750         cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4751
4752         if (check_error(__LINE__, cli1, ERRDOS, ERRbadshare, 
4753                         NT_STATUS_SHARING_VIOLATION)) {
4754                 printf("correct error code ERRDOS/ERRbadshare returned\n");
4755         }
4756
4757         status = cli_close(cli1, fnum1);
4758         if (!NT_STATUS_IS_OK(status)) {
4759                 printf("close2 failed (%s)\n", nt_errstr(status));
4760                 return False;
4761         }
4762
4763         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4764
4765         printf("finished open test 2\n");
4766
4767         /* Test truncate open disposition on file opened for read. */
4768         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4769         if (!NT_STATUS_IS_OK(status)) {
4770                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
4771                 return False;
4772         }
4773
4774         /* write 20 bytes. */
4775
4776         memset(buf, '\0', 20);
4777
4778         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
4779         if (!NT_STATUS_IS_OK(status)) {
4780                 printf("write failed (%s)\n", nt_errstr(status));
4781                 correct = False;
4782         }
4783
4784         status = cli_close(cli1, fnum1);
4785         if (!NT_STATUS_IS_OK(status)) {
4786                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
4787                 return False;
4788         }
4789
4790         /* Ensure size == 20. */
4791         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4792         if (!NT_STATUS_IS_OK(status)) {
4793                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4794                 return False;
4795         }
4796
4797         if (fsize != 20) {
4798                 printf("(3) file size != 20\n");
4799                 return False;
4800         }
4801
4802         /* Now test if we can truncate a file opened for readonly. */
4803         status = cli_open(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
4804         if (!NT_STATUS_IS_OK(status)) {
4805                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
4806                 return False;
4807         }
4808
4809         status = cli_close(cli1, fnum1);
4810         if (!NT_STATUS_IS_OK(status)) {
4811                 printf("close2 failed (%s)\n", nt_errstr(status));
4812                 return False;
4813         }
4814
4815         /* Ensure size == 0. */
4816         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4817         if (!NT_STATUS_IS_OK(status)) {
4818                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4819                 return False;
4820         }
4821
4822         if (fsize != 0) {
4823                 printf("(3) file size != 0\n");
4824                 return False;
4825         }
4826         printf("finished open test 3\n");
4827
4828         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4829
4830         printf("Do ctemp tests\n");
4831         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
4832         if (!NT_STATUS_IS_OK(status)) {
4833                 printf("ctemp failed (%s)\n", nt_errstr(status));
4834                 return False;
4835         }
4836
4837         printf("ctemp gave path %s\n", tmp_path);
4838         status = cli_close(cli1, fnum1);
4839         if (!NT_STATUS_IS_OK(status)) {
4840                 printf("close of temp failed (%s)\n", nt_errstr(status));
4841         }
4842
4843         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4844         if (!NT_STATUS_IS_OK(status)) {
4845                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
4846         }
4847
4848         /* Test the non-io opens... */
4849
4850         if (!torture_open_connection(&cli2, 1)) {
4851                 return False;
4852         }
4853
4854         cli_setatr(cli2, fname, 0, 0);
4855         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4856
4857         cli_sockopt(cli2, sockops);
4858
4859         printf("TEST #1 testing 2 non-io opens (no delete)\n");
4860         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
4861                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4862                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4863         if (!NT_STATUS_IS_OK(status)) {
4864                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4865                 return False;
4866         }
4867
4868         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
4869                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4870                               FILE_OPEN_IF, 0, 0, &fnum2);
4871         if (!NT_STATUS_IS_OK(status)) {
4872                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4873                 return False;
4874         }
4875
4876         status = cli_close(cli1, fnum1);
4877         if (!NT_STATUS_IS_OK(status)) {
4878                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
4879                 return False;
4880         }
4881
4882         status = cli_close(cli2, fnum2);
4883         if (!NT_STATUS_IS_OK(status)) {
4884                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
4885                 return False;
4886         }
4887
4888         printf("non-io open test #1 passed.\n");
4889
4890         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4891
4892         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
4893
4894         status = cli_ntcreate(cli1, fname, 0,
4895                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
4896                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4897                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4898         if (!NT_STATUS_IS_OK(status)) {
4899                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4900                 return False;
4901         }
4902
4903         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
4904                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4905                               FILE_OPEN_IF, 0, 0, &fnum2);
4906         if (!NT_STATUS_IS_OK(status)) {
4907                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4908                 return False;
4909         }
4910
4911         status = cli_close(cli1, fnum1);
4912         if (!NT_STATUS_IS_OK(status)) {
4913                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
4914                 return False;
4915         }
4916
4917         status = cli_close(cli2, fnum2);
4918         if (!NT_STATUS_IS_OK(status)) {
4919                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
4920                 return False;
4921         }
4922
4923         printf("non-io open test #2 passed.\n");
4924
4925         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4926
4927         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
4928
4929         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
4930                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4931                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4932         if (!NT_STATUS_IS_OK(status)) {
4933                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4934                 return False;
4935         }
4936
4937         status = cli_ntcreate(cli2, fname, 0,
4938                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
4939                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4940                               FILE_OPEN_IF, 0, 0, &fnum2);
4941         if (!NT_STATUS_IS_OK(status)) {
4942                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4943                 return False;
4944         }
4945
4946         status = cli_close(cli1, fnum1);
4947         if (!NT_STATUS_IS_OK(status)) {
4948                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
4949                 return False;
4950         }
4951
4952         status = cli_close(cli2, fnum2);
4953         if (!NT_STATUS_IS_OK(status)) {
4954                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
4955                 return False;
4956         }
4957
4958         printf("non-io open test #3 passed.\n");
4959
4960         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4961
4962         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
4963
4964         status = cli_ntcreate(cli1, fname, 0,
4965                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
4966                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4967                                FILE_OVERWRITE_IF, 0, 0, &fnum1);
4968         if (!NT_STATUS_IS_OK(status)) {
4969                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4970                 return False;
4971         }
4972
4973         status = cli_ntcreate(cli2, fname, 0,
4974                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
4975                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4976                               FILE_OPEN_IF, 0, 0, &fnum2);
4977         if (NT_STATUS_IS_OK(status)) {
4978                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
4979                 return False;
4980         }
4981
4982         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
4983
4984         status = cli_close(cli1, fnum1);
4985         if (!NT_STATUS_IS_OK(status)) {
4986                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
4987                 return False;
4988         }
4989
4990         printf("non-io open test #4 passed.\n");
4991
4992         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4993
4994         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
4995
4996         status = cli_ntcreate(cli1, fname, 0,
4997                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
4998                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
4999                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5000         if (!NT_STATUS_IS_OK(status)) {
5001                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5002                 return False;
5003         }
5004
5005         status = cli_ntcreate(cli2, fname, 0,
5006                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5007                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5008                               FILE_OPEN_IF, 0, 0, &fnum2);
5009         if (!NT_STATUS_IS_OK(status)) {
5010                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5011                 return False;
5012         }
5013
5014         status = cli_close(cli1, fnum1);
5015         if (!NT_STATUS_IS_OK(status)) {
5016                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5017                 return False;
5018         }
5019
5020         status = cli_close(cli2, fnum2);
5021         if (!NT_STATUS_IS_OK(status)) {
5022                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5023                 return False;
5024         }
5025
5026         printf("non-io open test #5 passed.\n");
5027
5028         printf("TEST #6 testing 1 non-io open, one io open\n");
5029
5030         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5031
5032         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5033                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5034                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5035         if (!NT_STATUS_IS_OK(status)) {
5036                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5037                 return False;
5038         }
5039
5040         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5041                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5042                               FILE_OPEN_IF, 0, 0, &fnum2);
5043         if (!NT_STATUS_IS_OK(status)) {
5044                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5045                 return False;
5046         }
5047
5048         status = cli_close(cli1, fnum1);
5049         if (!NT_STATUS_IS_OK(status)) {
5050                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5051                 return False;
5052         }
5053
5054         status = cli_close(cli2, fnum2);
5055         if (!NT_STATUS_IS_OK(status)) {
5056                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5057                 return False;
5058         }
5059
5060         printf("non-io open test #6 passed.\n");
5061
5062         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5063
5064         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5065
5066         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5067                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5068                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5069         if (!NT_STATUS_IS_OK(status)) {
5070                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5071                 return False;
5072         }
5073
5074         status = cli_ntcreate(cli2, fname, 0,
5075                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5076                               FILE_ATTRIBUTE_NORMAL,
5077                               FILE_SHARE_READ|FILE_SHARE_DELETE,
5078                               FILE_OPEN_IF, 0, 0, &fnum2);
5079         if (NT_STATUS_IS_OK(status)) {
5080                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5081                 return False;
5082         }
5083
5084         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5085
5086         status = cli_close(cli1, fnum1);
5087         if (!NT_STATUS_IS_OK(status)) {
5088                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5089                 return False;
5090         }
5091
5092         printf("non-io open test #7 passed.\n");
5093
5094         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5095
5096         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5097         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5098                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5099                                 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5100         if (!NT_STATUS_IS_OK(status)) {
5101                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5102                 correct = false;
5103                 goto out;
5104         }
5105
5106         /* Write to ensure we have to update the file time. */
5107         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5108                               NULL);
5109         if (!NT_STATUS_IS_OK(status)) {
5110                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5111                 correct = false;
5112                 goto out;
5113         }
5114
5115         status = cli_close(cli1, fnum1);
5116         if (!NT_STATUS_IS_OK(status)) {
5117                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5118                 correct = false;
5119         }
5120
5121   out:
5122
5123         if (!torture_close_connection(cli1)) {
5124                 correct = False;
5125         }
5126         if (!torture_close_connection(cli2)) {
5127                 correct = False;
5128         }
5129
5130         return correct;
5131 }
5132
5133 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5134 {
5135         uint16 major, minor;
5136         uint32 caplow, caphigh;
5137         NTSTATUS status;
5138
5139         if (!SERVER_HAS_UNIX_CIFS(cli)) {
5140                 printf("Server doesn't support UNIX CIFS extensions.\n");
5141                 return NT_STATUS_NOT_SUPPORTED;
5142         }
5143
5144         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5145                                              &caphigh);
5146         if (!NT_STATUS_IS_OK(status)) {
5147                 printf("Server didn't return UNIX CIFS extensions: %s\n",
5148                        nt_errstr(status));
5149                 return status;
5150         }
5151
5152         status = cli_set_unix_extensions_capabilities(cli, major, minor,
5153                                                       caplow, caphigh);
5154         if (!NT_STATUS_IS_OK(status)) {
5155                 printf("Server doesn't support setting UNIX CIFS extensions: "
5156                        "%s.\n", nt_errstr(status));
5157                 return status;
5158         }
5159
5160         return NT_STATUS_OK;
5161 }
5162
5163 /*
5164   Test POSIX open /mkdir calls.
5165  */
5166 static bool run_simple_posix_open_test(int dummy)
5167 {
5168         static struct cli_state *cli1;
5169         const char *fname = "posix:file";
5170         const char *hname = "posix:hlink";
5171         const char *sname = "posix:symlink";
5172         const char *dname = "posix:dir";
5173         char buf[10];
5174         char namebuf[11];
5175         uint16_t fnum1 = (uint16_t)-1;
5176         SMB_STRUCT_STAT sbuf;
5177         bool correct = false;
5178         NTSTATUS status;
5179
5180         printf("Starting simple POSIX open test\n");
5181
5182         if (!torture_open_connection(&cli1, 0)) {
5183                 return false;
5184         }
5185
5186         cli_sockopt(cli1, sockops);
5187
5188         status = torture_setup_unix_extensions(cli1);
5189         if (!NT_STATUS_IS_OK(status)) {
5190                 return false;
5191         }
5192
5193         cli_setatr(cli1, fname, 0, 0);
5194         cli_posix_unlink(cli1, fname);
5195         cli_setatr(cli1, dname, 0, 0);
5196         cli_posix_rmdir(cli1, dname);
5197         cli_setatr(cli1, hname, 0, 0);
5198         cli_posix_unlink(cli1, hname);
5199         cli_setatr(cli1, sname, 0, 0);
5200         cli_posix_unlink(cli1, sname);
5201
5202         /* Create a directory. */
5203         status = cli_posix_mkdir(cli1, dname, 0777);
5204         if (!NT_STATUS_IS_OK(status)) {
5205                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5206                 goto out;
5207         }
5208
5209         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5210                                 0600, &fnum1);
5211         if (!NT_STATUS_IS_OK(status)) {
5212                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5213                 goto out;
5214         }
5215
5216         /* Test ftruncate - set file size. */
5217         status = cli_ftruncate(cli1, fnum1, 1000);
5218         if (!NT_STATUS_IS_OK(status)) {
5219                 printf("ftruncate failed (%s)\n", nt_errstr(status));
5220                 goto out;
5221         }
5222
5223         /* Ensure st_size == 1000 */
5224         status = cli_posix_stat(cli1, fname, &sbuf);
5225         if (!NT_STATUS_IS_OK(status)) {
5226                 printf("stat failed (%s)\n", nt_errstr(status));
5227                 goto out;
5228         }
5229
5230         if (sbuf.st_ex_size != 1000) {
5231                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5232                 goto out;
5233         }
5234
5235         /* Test ftruncate - set file size back to zero. */
5236         status = cli_ftruncate(cli1, fnum1, 0);
5237         if (!NT_STATUS_IS_OK(status)) {
5238                 printf("ftruncate failed (%s)\n", nt_errstr(status));
5239                 goto out;
5240         }
5241
5242         status = cli_close(cli1, fnum1);
5243         if (!NT_STATUS_IS_OK(status)) {
5244                 printf("close failed (%s)\n", nt_errstr(status));
5245                 goto out;
5246         }
5247
5248         /* Now open the file again for read only. */
5249         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5250         if (!NT_STATUS_IS_OK(status)) {
5251                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5252                 goto out;
5253         }
5254
5255         /* Now unlink while open. */
5256         status = cli_posix_unlink(cli1, fname);
5257         if (!NT_STATUS_IS_OK(status)) {
5258                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5259                 goto out;
5260         }
5261
5262         status = cli_close(cli1, fnum1);
5263         if (!NT_STATUS_IS_OK(status)) {
5264                 printf("close(2) failed (%s)\n", nt_errstr(status));
5265                 goto out;
5266         }
5267
5268         /* Ensure the file has gone. */
5269         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5270         if (NT_STATUS_IS_OK(status)) {
5271                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5272                 goto out;
5273         }
5274
5275         /* Create again to test open with O_TRUNC. */
5276         if (!NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1))) {
5277                 printf("POSIX create of %s failed (%s)\n", fname, cli_errstr(cli1));
5278                 goto out;
5279         }
5280
5281         /* Test ftruncate - set file size. */
5282         if (!NT_STATUS_IS_OK(cli_ftruncate(cli1, fnum1, 1000))) {
5283                 printf("ftruncate failed (%s)\n", cli_errstr(cli1));
5284                 goto out;
5285         }
5286
5287         /* Ensure st_size == 1000 */
5288         if (!NT_STATUS_IS_OK(cli_posix_stat(cli1, fname, &sbuf))) {
5289                 printf("stat failed (%s)\n", cli_errstr(cli1));
5290                 goto out;
5291         }
5292
5293         if (sbuf.st_ex_size != 1000) {
5294                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5295                 goto out;
5296         }
5297
5298         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
5299                 printf("close(2) failed (%s)\n", cli_errstr(cli1));
5300                 goto out;
5301         }
5302
5303         /* Re-open with O_TRUNC. */
5304         if (!NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1))) {
5305                 printf("POSIX create of %s failed (%s)\n", fname, cli_errstr(cli1));
5306                 goto out;
5307         }
5308
5309         /* Ensure st_size == 0 */
5310         if (!NT_STATUS_IS_OK(cli_posix_stat(cli1, fname, &sbuf))) {
5311                 printf("stat failed (%s)\n", cli_errstr(cli1));
5312                 goto out;
5313         }
5314
5315         if (sbuf.st_ex_size != 0) {
5316                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5317                 goto out;
5318         }
5319
5320         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
5321                 printf("close failed (%s)\n", cli_errstr(cli1));
5322                 goto out;
5323         }
5324
5325         if (!NT_STATUS_IS_OK(cli_posix_unlink(cli1, fname))) {
5326                 printf("POSIX unlink of %s failed (%s)\n", fname, cli_errstr(cli1));
5327                 goto out;
5328         }
5329
5330         if (!NT_STATUS_IS_OK(cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1))) {
5331                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5332                         dname, cli_errstr(cli1));
5333                 goto out;
5334         }
5335
5336         cli_close(cli1, fnum1);
5337
5338         /* What happens when we try and POSIX open a directory for write ? */
5339         if (NT_STATUS_IS_OK(cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1))) {
5340                 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5341                 goto out;
5342         } else {
5343                 if (!check_error(__LINE__, cli1, ERRDOS, EISDIR,
5344                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5345                         goto out;
5346                 }
5347         }
5348
5349         /* Create the file. */
5350         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5351                                 0600, &fnum1);
5352         if (!NT_STATUS_IS_OK(status)) {
5353                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5354                 goto out;
5355         }
5356
5357         /* Write some data into it. */
5358         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5359                               NULL);
5360         if (!NT_STATUS_IS_OK(status)) {
5361                 printf("cli_write failed: %s\n", nt_errstr(status));
5362                 goto out;
5363         }
5364
5365         cli_close(cli1, fnum1);
5366
5367         /* Now create a hardlink. */
5368         status = cli_posix_hardlink(cli1, fname, hname);
5369         if (!NT_STATUS_IS_OK(status)) {
5370                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5371                 goto out;
5372         }
5373
5374         /* Now create a symlink. */
5375         status = cli_posix_symlink(cli1, fname, sname);
5376         if (!NT_STATUS_IS_OK(status)) {
5377                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5378                 goto out;
5379         }
5380
5381         /* Open the hardlink for read. */
5382         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5383         if (!NT_STATUS_IS_OK(status)) {
5384                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5385                 goto out;
5386         }
5387
5388         if (cli_read(cli1, fnum1, buf, 0, 10) != 10) {
5389                 printf("POSIX read of %s failed (%s)\n", hname, cli_errstr(cli1));
5390                 goto out;
5391         }
5392
5393         if (memcmp(buf, "TEST DATA\n", 10)) {
5394                 printf("invalid data read from hardlink\n");
5395                 goto out;
5396         }
5397
5398         /* Do a POSIX lock/unlock. */
5399         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5400         if (!NT_STATUS_IS_OK(status)) {
5401                 printf("POSIX lock failed %s\n", nt_errstr(status));
5402                 goto out;
5403         }
5404
5405         /* Punch a hole in the locked area. */
5406         status = cli_posix_unlock(cli1, fnum1, 10, 80);
5407         if (!NT_STATUS_IS_OK(status)) {
5408                 printf("POSIX unlock failed %s\n", nt_errstr(status));
5409                 goto out;
5410         }
5411
5412         cli_close(cli1, fnum1);
5413
5414         /* Open the symlink for read - this should fail. A POSIX
5415            client should not be doing opens on a symlink. */
5416         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5417         if (NT_STATUS_IS_OK(status)) {
5418                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5419                 goto out;
5420         } else {
5421                 if (!check_error(__LINE__, cli1, ERRDOS, ERRbadpath,
5422                                 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5423                         printf("POSIX open of %s should have failed "
5424                                 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5425                                 "failed with %s instead.\n",
5426                                 sname, nt_errstr(status));
5427                         goto out;
5428                 }
5429         }
5430
5431         status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5432         if (!NT_STATUS_IS_OK(status)) {
5433                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5434                 goto out;
5435         }
5436
5437         if (strcmp(namebuf, fname) != 0) {
5438                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5439                         sname, fname, namebuf);
5440                 goto out;
5441         }
5442
5443         status = cli_posix_rmdir(cli1, dname);
5444         if (!NT_STATUS_IS_OK(status)) {
5445                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5446                 goto out;
5447         }
5448
5449         printf("Simple POSIX open test passed\n");
5450         correct = true;
5451
5452   out:
5453
5454         if (fnum1 != (uint16_t)-1) {
5455                 cli_close(cli1, fnum1);
5456                 fnum1 = (uint16_t)-1;
5457         }
5458
5459         cli_setatr(cli1, sname, 0, 0);
5460         cli_posix_unlink(cli1, sname);
5461         cli_setatr(cli1, hname, 0, 0);
5462         cli_posix_unlink(cli1, hname);
5463         cli_setatr(cli1, fname, 0, 0);
5464         cli_posix_unlink(cli1, fname);
5465         cli_setatr(cli1, dname, 0, 0);
5466         cli_posix_rmdir(cli1, dname);
5467
5468         if (!torture_close_connection(cli1)) {
5469                 correct = false;
5470         }
5471
5472         return correct;
5473 }
5474
5475
5476 static uint32 open_attrs_table[] = {
5477                 FILE_ATTRIBUTE_NORMAL,
5478                 FILE_ATTRIBUTE_ARCHIVE,
5479                 FILE_ATTRIBUTE_READONLY,
5480                 FILE_ATTRIBUTE_HIDDEN,
5481                 FILE_ATTRIBUTE_SYSTEM,
5482
5483                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
5484                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
5485                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
5486                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5487                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5488                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5489
5490                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5491                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5492                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5493                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
5494 };
5495
5496 struct trunc_open_results {
5497         unsigned int num;
5498         uint32 init_attr;
5499         uint32 trunc_attr;
5500         uint32 result_attr;
5501 };
5502
5503 static struct trunc_open_results attr_results[] = {
5504         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5505         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5506         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5507         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5508         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5509         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5510         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5511         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5512         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5513         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5514         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5515         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5516         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5517         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5518         { 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 },
5519         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5520         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5521         { 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 },
5522         { 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 },
5523         { 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 },
5524         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5525         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5526         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5527         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5528         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5529         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
5530 };
5531
5532 static bool run_openattrtest(int dummy)
5533 {
5534         static struct cli_state *cli1;
5535         const char *fname = "\\openattr.file";
5536         uint16_t fnum1;
5537         bool correct = True;
5538         uint16 attr;
5539         unsigned int i, j, k, l;
5540         NTSTATUS status;
5541
5542         printf("starting open attr test\n");
5543
5544         if (!torture_open_connection(&cli1, 0)) {
5545                 return False;
5546         }
5547
5548         cli_sockopt(cli1, sockops);
5549
5550         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
5551                 cli_setatr(cli1, fname, 0, 0);
5552                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5553
5554                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
5555                                        open_attrs_table[i], FILE_SHARE_NONE,
5556                                        FILE_OVERWRITE_IF, 0, 0, &fnum1);
5557                 if (!NT_STATUS_IS_OK(status)) {
5558                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5559                         return False;
5560                 }
5561
5562                 status = cli_close(cli1, fnum1);
5563                 if (!NT_STATUS_IS_OK(status)) {
5564                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5565                         return False;
5566                 }
5567
5568                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
5569                         status = cli_ntcreate(cli1, fname, 0,
5570                                               FILE_READ_DATA|FILE_WRITE_DATA,
5571                                               open_attrs_table[j],
5572                                               FILE_SHARE_NONE, FILE_OVERWRITE,
5573                                               0, 0, &fnum1);
5574                         if (!NT_STATUS_IS_OK(status)) {
5575                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5576                                         if (attr_results[l].num == k) {
5577                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
5578                                                                 k, open_attrs_table[i],
5579                                                                 open_attrs_table[j],
5580                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
5581                                                 correct = False;
5582                                         }
5583                                 }
5584
5585                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5586                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
5587                                                         k, open_attrs_table[i], open_attrs_table[j],
5588                                                         nt_errstr(status));
5589                                         correct = False;
5590                                 }
5591 #if 0
5592                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
5593 #endif
5594                                 k++;
5595                                 continue;
5596                         }
5597
5598                         status = cli_close(cli1, fnum1);
5599                         if (!NT_STATUS_IS_OK(status)) {
5600                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
5601                                 return False;
5602                         }
5603
5604                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
5605                         if (!NT_STATUS_IS_OK(status)) {
5606                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
5607                                 return False;
5608                         }
5609
5610 #if 0
5611                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
5612                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
5613 #endif
5614
5615                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5616                                 if (attr_results[l].num == k) {
5617                                         if (attr != attr_results[l].result_attr ||
5618                                                         open_attrs_table[i] != attr_results[l].init_attr ||
5619                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
5620                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
5621                                                 open_attrs_table[i],
5622                                                 open_attrs_table[j],
5623                                                 (unsigned int)attr,
5624                                                 attr_results[l].result_attr);
5625                                                 correct = False;
5626                                         }
5627                                         break;
5628                                 }
5629                         }
5630                         k++;
5631                 }
5632         }
5633
5634         cli_setatr(cli1, fname, 0, 0);
5635         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5636
5637         printf("open attr test %s.\n", correct ? "passed" : "failed");
5638
5639         if (!torture_close_connection(cli1)) {
5640                 correct = False;
5641         }
5642         return correct;
5643 }
5644
5645 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
5646                     const char *name, void *state)
5647 {
5648         int *matched = (int *)state;
5649         if (matched != NULL) {
5650                 *matched += 1;
5651         }
5652         return NT_STATUS_OK;
5653 }
5654
5655 /*
5656   test directory listing speed
5657  */
5658 static bool run_dirtest(int dummy)
5659 {
5660         int i;
5661         static struct cli_state *cli;
5662         uint16_t fnum;
5663         struct timeval core_start;
5664         bool correct = True;
5665         int matched;
5666
5667         printf("starting directory test\n");
5668
5669         if (!torture_open_connection(&cli, 0)) {
5670                 return False;
5671         }
5672
5673         cli_sockopt(cli, sockops);
5674
5675         srandom(0);
5676         for (i=0;i<torture_numops;i++) {
5677                 fstring fname;
5678                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5679                 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
5680                         fprintf(stderr,"Failed to open %s\n", fname);
5681                         return False;
5682                 }
5683                 cli_close(cli, fnum);
5684         }
5685
5686         core_start = timeval_current();
5687
5688         matched = 0;
5689         cli_list(cli, "a*.*", 0, list_fn, &matched);
5690         printf("Matched %d\n", matched);
5691
5692         matched = 0;
5693         cli_list(cli, "b*.*", 0, list_fn, &matched);
5694         printf("Matched %d\n", matched);
5695
5696         matched = 0;
5697         cli_list(cli, "xyzabc", 0, list_fn, &matched);
5698         printf("Matched %d\n", matched);
5699
5700         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
5701
5702         srandom(0);
5703         for (i=0;i<torture_numops;i++) {
5704                 fstring fname;
5705                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5706                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5707         }
5708
5709         if (!torture_close_connection(cli)) {
5710                 correct = False;
5711         }
5712
5713         printf("finished dirtest\n");
5714
5715         return correct;
5716 }
5717
5718 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
5719                    void *state)
5720 {
5721         struct cli_state *pcli = (struct cli_state *)state;
5722         fstring fname;
5723         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
5724
5725         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
5726                 return NT_STATUS_OK;
5727
5728         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
5729                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
5730                         printf("del_fn: failed to rmdir %s\n,", fname );
5731         } else {
5732                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
5733                         printf("del_fn: failed to unlink %s\n,", fname );
5734         }
5735         return NT_STATUS_OK;
5736 }
5737
5738
5739 /*
5740   sees what IOCTLs are supported
5741  */
5742 bool torture_ioctl_test(int dummy)
5743 {
5744         static struct cli_state *cli;
5745         uint16_t device, function;
5746         uint16_t fnum;
5747         const char *fname = "\\ioctl.dat";
5748         DATA_BLOB blob;
5749         NTSTATUS status;
5750
5751         if (!torture_open_connection(&cli, 0)) {
5752                 return False;
5753         }
5754
5755         printf("starting ioctl test\n");
5756
5757         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5758
5759         status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5760         if (!NT_STATUS_IS_OK(status)) {
5761                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5762                 return False;
5763         }
5764
5765         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
5766         printf("ioctl device info: %s\n", nt_errstr(status));
5767
5768         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
5769         printf("ioctl job info: %s\n", nt_errstr(status));
5770
5771         for (device=0;device<0x100;device++) {
5772                 printf("ioctl test with device = 0x%x\n", device);
5773                 for (function=0;function<0x100;function++) {
5774                         uint32 code = (device<<16) | function;
5775
5776                         status = cli_raw_ioctl(cli, fnum, code, &blob);
5777
5778                         if (NT_STATUS_IS_OK(status)) {
5779                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
5780                                        (int)blob.length);
5781                                 data_blob_free(&blob);
5782                         }
5783                 }
5784         }
5785
5786         if (!torture_close_connection(cli)) {
5787                 return False;
5788         }
5789
5790         return True;
5791 }
5792
5793
5794 /*
5795   tries varients of chkpath
5796  */
5797 bool torture_chkpath_test(int dummy)
5798 {
5799         static struct cli_state *cli;
5800         uint16_t fnum;
5801         bool ret;
5802         NTSTATUS status;
5803
5804         if (!torture_open_connection(&cli, 0)) {
5805                 return False;
5806         }
5807
5808         printf("starting chkpath test\n");
5809
5810         /* cleanup from an old run */
5811         cli_rmdir(cli, "\\chkpath.dir\\dir2");
5812         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5813         cli_rmdir(cli, "\\chkpath.dir");
5814
5815         status = cli_mkdir(cli, "\\chkpath.dir");
5816         if (!NT_STATUS_IS_OK(status)) {
5817                 printf("mkdir1 failed : %s\n", nt_errstr(status));
5818                 return False;
5819         }
5820
5821         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
5822         if (!NT_STATUS_IS_OK(status)) {
5823                 printf("mkdir2 failed : %s\n", nt_errstr(status));
5824                 return False;
5825         }
5826
5827         status = cli_open(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
5828                           DENY_NONE, &fnum);
5829         if (!NT_STATUS_IS_OK(status)) {
5830                 printf("open1 failed (%s)\n", nt_errstr(status));
5831                 return False;
5832         }
5833         cli_close(cli, fnum);
5834
5835         status = cli_chkpath(cli, "\\chkpath.dir");
5836         if (!NT_STATUS_IS_OK(status)) {
5837                 printf("chkpath1 failed: %s\n", nt_errstr(status));
5838                 ret = False;
5839         }
5840
5841         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
5842         if (!NT_STATUS_IS_OK(status)) {
5843                 printf("chkpath2 failed: %s\n", nt_errstr(status));
5844                 ret = False;
5845         }
5846
5847         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
5848         if (!NT_STATUS_IS_OK(status)) {
5849                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath, 
5850                                   NT_STATUS_NOT_A_DIRECTORY);
5851         } else {
5852                 printf("* chkpath on a file should fail\n");
5853                 ret = False;
5854         }
5855
5856         if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\bar.txt"))) {
5857                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadfile, 
5858                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
5859         } else {
5860                 printf("* chkpath on a non existant file should fail\n");
5861                 ret = False;
5862         }
5863
5864         if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt"))) {
5865                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath, 
5866                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
5867         } else {
5868                 printf("* chkpath on a non existent component should fail\n");
5869                 ret = False;
5870         }
5871
5872         cli_rmdir(cli, "\\chkpath.dir\\dir2");
5873         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5874         cli_rmdir(cli, "\\chkpath.dir");
5875
5876         if (!torture_close_connection(cli)) {
5877                 return False;
5878         }
5879
5880         return ret;
5881 }
5882
5883 static bool run_eatest(int dummy)
5884 {
5885         static struct cli_state *cli;
5886         const char *fname = "\\eatest.txt";
5887         bool correct = True;
5888         uint16_t fnum;
5889         int i;
5890         size_t num_eas;
5891         struct ea_struct *ea_list = NULL;
5892         TALLOC_CTX *mem_ctx = talloc_init("eatest");
5893         NTSTATUS status;
5894
5895         printf("starting eatest\n");
5896
5897         if (!torture_open_connection(&cli, 0)) {
5898                 talloc_destroy(mem_ctx);
5899                 return False;
5900         }
5901
5902         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5903
5904         status = cli_ntcreate(cli, fname, 0,
5905                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
5906                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
5907                               0x4044, 0, &fnum);
5908         if (!NT_STATUS_IS_OK(status)) {
5909                 printf("open failed - %s\n", nt_errstr(status));
5910                 talloc_destroy(mem_ctx);
5911                 return False;
5912         }
5913
5914         for (i = 0; i < 10; i++) {
5915                 fstring ea_name, ea_val;
5916
5917                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
5918                 memset(ea_val, (char)i+1, i+1);
5919                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
5920                 if (!NT_STATUS_IS_OK(status)) {
5921                         printf("ea_set of name %s failed - %s\n", ea_name,
5922                                nt_errstr(status));
5923                         talloc_destroy(mem_ctx);
5924                         return False;
5925                 }
5926         }
5927
5928         cli_close(cli, fnum);
5929         for (i = 0; i < 10; i++) {
5930                 fstring ea_name, ea_val;
5931
5932                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
5933                 memset(ea_val, (char)i+1, i+1);
5934                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
5935                 if (!NT_STATUS_IS_OK(status)) {
5936                         printf("ea_set of name %s failed - %s\n", ea_name,
5937                                nt_errstr(status));
5938                         talloc_destroy(mem_ctx);
5939                         return False;
5940                 }
5941         }
5942
5943         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
5944         if (!NT_STATUS_IS_OK(status)) {
5945                 printf("ea_get list failed - %s\n", nt_errstr(status));
5946                 correct = False;
5947         }
5948
5949         printf("num_eas = %d\n", (int)num_eas);
5950
5951         if (num_eas != 20) {
5952                 printf("Should be 20 EA's stored... failing.\n");
5953                 correct = False;
5954         }
5955
5956         for (i = 0; i < num_eas; i++) {
5957                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
5958                 dump_data(0, ea_list[i].value.data,
5959                           ea_list[i].value.length);
5960         }
5961
5962         /* Setting EA's to zero length deletes them. Test this */
5963         printf("Now deleting all EA's - case indepenent....\n");
5964
5965 #if 1
5966         cli_set_ea_path(cli, fname, "", "", 0);
5967 #else
5968         for (i = 0; i < 20; i++) {
5969                 fstring ea_name;
5970                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
5971                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
5972                 if (!NT_STATUS_IS_OK(status)) {
5973                         printf("ea_set of name %s failed - %s\n", ea_name,
5974                                nt_errstr(status));
5975                         talloc_destroy(mem_ctx);
5976                         return False;
5977                 }
5978         }
5979 #endif
5980
5981         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
5982         if (!NT_STATUS_IS_OK(status)) {
5983                 printf("ea_get list failed - %s\n", nt_errstr(status));
5984                 correct = False;
5985         }
5986
5987         printf("num_eas = %d\n", (int)num_eas);
5988         for (i = 0; i < num_eas; i++) {
5989                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
5990                 dump_data(0, ea_list[i].value.data,
5991                           ea_list[i].value.length);
5992         }
5993
5994         if (num_eas != 0) {
5995                 printf("deleting EA's failed.\n");
5996                 correct = False;
5997         }
5998
5999         /* Try and delete a non existant EA. */
6000         status = cli_set_ea_path(cli, fname, "foo", "", 0);
6001         if (!NT_STATUS_IS_OK(status)) {
6002                 printf("deleting non-existant EA 'foo' should succeed. %s\n",
6003                        nt_errstr(status));
6004                 correct = False;
6005         }
6006
6007         talloc_destroy(mem_ctx);
6008         if (!torture_close_connection(cli)) {
6009                 correct = False;
6010         }
6011
6012         return correct;
6013 }
6014
6015 static bool run_dirtest1(int dummy)
6016 {
6017         int i;
6018         static struct cli_state *cli;
6019         uint16_t fnum;
6020         int num_seen;
6021         bool correct = True;
6022
6023         printf("starting directory test\n");
6024
6025         if (!torture_open_connection(&cli, 0)) {
6026                 return False;
6027         }
6028
6029         cli_sockopt(cli, sockops);
6030
6031         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6032         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6033         cli_rmdir(cli, "\\LISTDIR");
6034         cli_mkdir(cli, "\\LISTDIR");
6035
6036         /* Create 1000 files and 1000 directories. */
6037         for (i=0;i<1000;i++) {
6038                 fstring fname;
6039                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
6040                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6041                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6042                         fprintf(stderr,"Failed to open %s\n", fname);
6043                         return False;
6044                 }
6045                 cli_close(cli, fnum);
6046         }
6047         for (i=0;i<1000;i++) {
6048                 fstring fname;
6049                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
6050                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
6051                         fprintf(stderr,"Failed to open %s\n", fname);
6052                         return False;
6053                 }
6054         }
6055
6056         /* Now ensure that doing an old list sees both files and directories. */
6057         num_seen = 0;
6058         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6059         printf("num_seen = %d\n", num_seen );
6060         /* We should see 100 files + 1000 directories + . and .. */
6061         if (num_seen != 2002)
6062                 correct = False;
6063
6064         /* Ensure if we have the "must have" bits we only see the
6065          * relevent entries.
6066          */
6067         num_seen = 0;
6068         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6069         printf("num_seen = %d\n", num_seen );
6070         if (num_seen != 1002)
6071                 correct = False;
6072
6073         num_seen = 0;
6074         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6075         printf("num_seen = %d\n", num_seen );
6076         if (num_seen != 1000)
6077                 correct = False;
6078
6079         /* Delete everything. */
6080         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6081         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6082         cli_rmdir(cli, "\\LISTDIR");
6083
6084 #if 0
6085         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
6086         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
6087         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
6088 #endif
6089
6090         if (!torture_close_connection(cli)) {
6091                 correct = False;
6092         }
6093
6094         printf("finished dirtest1\n");
6095
6096         return correct;
6097 }
6098
6099 static bool run_error_map_extract(int dummy) {
6100
6101         static struct cli_state *c_dos;
6102         static struct cli_state *c_nt;
6103         NTSTATUS status;
6104
6105         uint32 error;
6106
6107         uint32 flgs2, errnum;
6108         uint8 errclass;
6109
6110         NTSTATUS nt_status;
6111
6112         fstring user;
6113
6114         /* NT-Error connection */
6115
6116         if (!(c_nt = open_nbt_connection())) {
6117                 return False;
6118         }
6119
6120         c_nt->use_spnego = False;
6121
6122         status = cli_negprot(c_nt);
6123
6124         if (!NT_STATUS_IS_OK(status)) {
6125                 printf("%s rejected the NT-error negprot (%s)\n", host,
6126                        nt_errstr(status));
6127                 cli_shutdown(c_nt);
6128                 return False;
6129         }
6130
6131         status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
6132         if (!NT_STATUS_IS_OK(status)) {
6133                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
6134                 return False;
6135         }
6136
6137         /* DOS-Error connection */
6138
6139         if (!(c_dos = open_nbt_connection())) {
6140                 return False;
6141         }
6142
6143         c_dos->use_spnego = False;
6144         c_dos->force_dos_errors = True;
6145
6146         status = cli_negprot(c_dos);
6147         if (!NT_STATUS_IS_OK(status)) {
6148                 printf("%s rejected the DOS-error negprot (%s)\n", host,
6149                        nt_errstr(status));
6150                 cli_shutdown(c_dos);
6151                 return False;
6152         }
6153
6154         status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
6155         if (!NT_STATUS_IS_OK(status)) {
6156                 printf("%s rejected the DOS-error initial session setup (%s)\n",
6157                         host, nt_errstr(status));
6158                 return False;
6159         }
6160
6161         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
6162                 fstr_sprintf(user, "%X", error);
6163
6164                 status = cli_session_setup(c_nt, user,
6165                                            password, strlen(password),
6166                                            password, strlen(password),
6167                                            workgroup);
6168                 if (NT_STATUS_IS_OK(status)) {
6169                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
6170                 }
6171
6172                 flgs2 = SVAL(c_nt->inbuf,smb_flg2);
6173
6174                 /* Case #1: 32-bit NT errors */
6175                 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
6176                         nt_status = NT_STATUS(IVAL(c_nt->inbuf,smb_rcls));
6177                 } else {
6178                         printf("/** Dos error on NT connection! (%s) */\n", 
6179                                cli_errstr(c_nt));
6180                         nt_status = NT_STATUS(0xc0000000);
6181                 }
6182
6183                 if (NT_STATUS_IS_OK(cli_session_setup(c_dos, user, 
6184                                                       password, strlen(password),
6185                                                       password, strlen(password),
6186                                                       workgroup))) {
6187                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
6188                 }
6189                 flgs2 = SVAL(c_dos->inbuf,smb_flg2), errnum;
6190
6191                 /* Case #1: 32-bit NT errors */
6192                 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
6193                         printf("/** NT error on DOS connection! (%s) */\n", 
6194                                cli_errstr(c_nt));
6195                         errnum = errclass = 0;
6196                 } else {
6197                         cli_dos_error(c_dos, &errclass, &errnum);
6198                 }
6199
6200                 if (NT_STATUS_V(nt_status) != error) { 
6201                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
6202                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
6203                                get_nt_error_c_code(talloc_tos(), nt_status));
6204                 }
6205
6206                 printf("\t{%s,\t%s,\t%s},\n", 
6207                        smb_dos_err_class(errclass), 
6208                        smb_dos_err_name(errclass, errnum), 
6209                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
6210         }
6211         return True;
6212 }
6213
6214 static bool run_sesssetup_bench(int dummy)
6215 {
6216         static struct cli_state *c;
6217         const char *fname = "\\file.dat";
6218         uint16_t fnum;
6219         NTSTATUS status;
6220         int i;
6221
6222         if (!torture_open_connection(&c, 0)) {
6223                 return false;
6224         }
6225
6226         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6227                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6228                               FILE_DELETE_ON_CLOSE, 0, &fnum);
6229         if (!NT_STATUS_IS_OK(status)) {
6230                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6231                 return false;
6232         }
6233
6234         for (i=0; i<torture_numops; i++) {
6235                 status = cli_session_setup(
6236                         c, username,
6237                         password, strlen(password),
6238                         password, strlen(password),
6239                         workgroup);
6240                 if (!NT_STATUS_IS_OK(status)) {
6241                         d_printf("(%s) cli_session_setup failed: %s\n",
6242                                  __location__, nt_errstr(status));
6243                         return false;
6244                 }
6245
6246                 d_printf("\r%d   ", (int)c->vuid);
6247
6248                 status = cli_ulogoff(c);
6249                 if (!NT_STATUS_IS_OK(status)) {
6250                         d_printf("(%s) cli_ulogoff failed: %s\n",
6251                                  __location__, nt_errstr(status));
6252                         return false;
6253                 }
6254                 c->vuid = 0;
6255         }
6256
6257         return true;
6258 }
6259
6260 static bool subst_test(const char *str, const char *user, const char *domain,
6261                        uid_t uid, gid_t gid, const char *expected)
6262 {
6263         char *subst;
6264         bool result = true;
6265
6266         subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
6267
6268         if (strcmp(subst, expected) != 0) {
6269                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
6270                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
6271                        expected);
6272                 result = false;
6273         }
6274
6275         TALLOC_FREE(subst);
6276         return result;
6277 }
6278
6279 static void chain1_open_completion(struct tevent_req *req)
6280 {
6281         uint16_t fnum;
6282         NTSTATUS status;
6283         status = cli_open_recv(req, &fnum);
6284         TALLOC_FREE(req);
6285
6286         d_printf("cli_open_recv returned %s: %d\n",
6287                  nt_errstr(status),
6288                  NT_STATUS_IS_OK(status) ? fnum : -1);
6289 }
6290
6291 static void chain1_write_completion(struct tevent_req *req)
6292 {
6293         size_t written;
6294         NTSTATUS status;
6295         status = cli_write_andx_recv(req, &written);
6296         TALLOC_FREE(req);
6297
6298         d_printf("cli_write_andx_recv returned %s: %d\n",
6299                  nt_errstr(status),
6300                  NT_STATUS_IS_OK(status) ? (int)written : -1);
6301 }
6302
6303 static void chain1_close_completion(struct tevent_req *req)
6304 {
6305         NTSTATUS status;
6306         bool *done = (bool *)tevent_req_callback_data_void(req);
6307
6308         status = cli_close_recv(req);
6309         *done = true;
6310
6311         TALLOC_FREE(req);
6312
6313         d_printf("cli_close returned %s\n", nt_errstr(status));
6314 }
6315
6316 static bool run_chain1(int dummy)
6317 {
6318         struct cli_state *cli1;
6319         struct event_context *evt = event_context_init(NULL);
6320         struct tevent_req *reqs[3], *smbreqs[3];
6321         bool done = false;
6322         const char *str = "foobar";
6323         NTSTATUS status;
6324
6325         printf("starting chain1 test\n");
6326         if (!torture_open_connection(&cli1, 0)) {
6327                 return False;
6328         }
6329
6330         cli_sockopt(cli1, sockops);
6331
6332         reqs[0] = cli_open_create(talloc_tos(), evt, cli1, "\\test",
6333                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
6334         if (reqs[0] == NULL) return false;
6335         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
6336
6337
6338         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
6339                                         (const uint8_t *)str, 0, strlen(str)+1,
6340                                         smbreqs, 1, &smbreqs[1]);
6341         if (reqs[1] == NULL) return false;
6342         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
6343
6344         reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
6345         if (reqs[2] == NULL) return false;
6346         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
6347
6348         status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6349         if (!NT_STATUS_IS_OK(status)) {
6350                 return false;
6351         }
6352
6353         while (!done) {
6354                 event_loop_once(evt);
6355         }
6356
6357         torture_close_connection(cli1);
6358         return True;
6359 }
6360
6361 static void chain2_sesssetup_completion(struct tevent_req *req)
6362 {
6363         NTSTATUS status;
6364         status = cli_session_setup_guest_recv(req);
6365         d_printf("sesssetup returned %s\n", nt_errstr(status));
6366 }
6367
6368 static void chain2_tcon_completion(struct tevent_req *req)
6369 {
6370         bool *done = (bool *)tevent_req_callback_data_void(req);
6371         NTSTATUS status;
6372         status = cli_tcon_andx_recv(req);
6373         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
6374         *done = true;
6375 }
6376
6377 static bool run_chain2(int dummy)
6378 {
6379         struct cli_state *cli1;
6380         struct event_context *evt = event_context_init(NULL);
6381         struct tevent_req *reqs[2], *smbreqs[2];
6382         bool done = false;
6383         NTSTATUS status;
6384
6385         printf("starting chain2 test\n");
6386         status = cli_start_connection(&cli1, global_myname(), host, NULL,
6387                                       port_to_use, Undefined, 0);
6388         if (!NT_STATUS_IS_OK(status)) {
6389                 return False;
6390         }
6391
6392         cli_sockopt(cli1, sockops);
6393
6394         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
6395                                                  &smbreqs[0]);
6396         if (reqs[0] == NULL) return false;
6397         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
6398
6399         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
6400                                        "?????", NULL, 0, &smbreqs[1]);
6401         if (reqs[1] == NULL) return false;
6402         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
6403
6404         status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6405         if (!NT_STATUS_IS_OK(status)) {
6406                 return false;
6407         }
6408
6409         while (!done) {
6410                 event_loop_once(evt);
6411         }
6412
6413         torture_close_connection(cli1);
6414         return True;
6415 }
6416
6417
6418 struct torture_createdel_state {
6419         struct tevent_context *ev;
6420         struct cli_state *cli;
6421 };
6422
6423 static void torture_createdel_created(struct tevent_req *subreq);
6424 static void torture_createdel_closed(struct tevent_req *subreq);
6425
6426 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
6427                                                  struct tevent_context *ev,
6428                                                  struct cli_state *cli,
6429                                                  const char *name)
6430 {
6431         struct tevent_req *req, *subreq;
6432         struct torture_createdel_state *state;
6433
6434         req = tevent_req_create(mem_ctx, &state,
6435                                 struct torture_createdel_state);
6436         if (req == NULL) {
6437                 return NULL;
6438         }
6439         state->ev = ev;
6440         state->cli = cli;
6441
6442         subreq = cli_ntcreate_send(
6443                 state, ev, cli, name, 0,
6444                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
6445                 FILE_ATTRIBUTE_NORMAL,
6446                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6447                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
6448
6449         if (tevent_req_nomem(subreq, req)) {
6450                 return tevent_req_post(req, ev);
6451         }
6452         tevent_req_set_callback(subreq, torture_createdel_created, req);
6453         return req;
6454 }
6455
6456 static void torture_createdel_created(struct tevent_req *subreq)
6457 {
6458         struct tevent_req *req = tevent_req_callback_data(
6459                 subreq, struct tevent_req);
6460         struct torture_createdel_state *state = tevent_req_data(
6461                 req, struct torture_createdel_state);
6462         NTSTATUS status;
6463         uint16_t fnum;
6464
6465         status = cli_ntcreate_recv(subreq, &fnum);
6466         TALLOC_FREE(subreq);
6467         if (!NT_STATUS_IS_OK(status)) {
6468                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
6469                            nt_errstr(status)));
6470                 tevent_req_nterror(req, status);
6471                 return;
6472         }
6473
6474         subreq = cli_close_send(state, state->ev, state->cli, fnum);
6475         if (tevent_req_nomem(subreq, req)) {
6476                 return;
6477         }
6478         tevent_req_set_callback(subreq, torture_createdel_closed, req);
6479 }
6480
6481 static void torture_createdel_closed(struct tevent_req *subreq)
6482 {
6483         struct tevent_req *req = tevent_req_callback_data(
6484                 subreq, struct tevent_req);
6485         NTSTATUS status;
6486
6487         status = cli_close_recv(subreq);
6488         if (!NT_STATUS_IS_OK(status)) {
6489                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
6490                 tevent_req_nterror(req, status);
6491                 return;
6492         }
6493         tevent_req_done(req);
6494 }
6495
6496 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
6497 {
6498         return tevent_req_simple_recv_ntstatus(req);
6499 }
6500
6501 struct torture_createdels_state {
6502         struct tevent_context *ev;
6503         struct cli_state *cli;
6504         const char *base_name;
6505         int sent;
6506         int received;
6507         int num_files;
6508         struct tevent_req **reqs;
6509 };
6510
6511 static void torture_createdels_done(struct tevent_req *subreq);
6512
6513 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
6514                                                   struct tevent_context *ev,
6515                                                   struct cli_state *cli,
6516                                                   const char *base_name,
6517                                                   int num_parallel,
6518                                                   int num_files)
6519 {
6520         struct tevent_req *req;
6521         struct torture_createdels_state *state;
6522         int i;
6523
6524         req = tevent_req_create(mem_ctx, &state,
6525                                 struct torture_createdels_state);
6526         if (req == NULL) {
6527                 return NULL;
6528         }
6529         state->ev = ev;
6530         state->cli = cli;
6531         state->base_name = talloc_strdup(state, base_name);
6532         if (tevent_req_nomem(state->base_name, req)) {
6533                 return tevent_req_post(req, ev);
6534         }
6535         state->num_files = MAX(num_parallel, num_files);
6536         state->sent = 0;
6537         state->received = 0;
6538
6539         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
6540         if (tevent_req_nomem(state->reqs, req)) {
6541                 return tevent_req_post(req, ev);
6542         }
6543
6544         for (i=0; i<num_parallel; i++) {
6545                 char *name;
6546
6547                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6548                                        state->sent);
6549                 if (tevent_req_nomem(name, req)) {
6550                         return tevent_req_post(req, ev);
6551                 }
6552                 state->reqs[i] = torture_createdel_send(
6553                         state->reqs, state->ev, state->cli, name);
6554                 if (tevent_req_nomem(state->reqs[i], req)) {
6555                         return tevent_req_post(req, ev);
6556                 }
6557                 name = talloc_move(state->reqs[i], &name);
6558                 tevent_req_set_callback(state->reqs[i],
6559                                         torture_createdels_done, req);
6560                 state->sent += 1;
6561         }
6562         return req;
6563 }
6564
6565 static void torture_createdels_done(struct tevent_req *subreq)
6566 {
6567         struct tevent_req *req = tevent_req_callback_data(
6568                 subreq, struct tevent_req);
6569         struct torture_createdels_state *state = tevent_req_data(
6570                 req, struct torture_createdels_state);
6571         size_t num_parallel = talloc_array_length(state->reqs);
6572         NTSTATUS status;
6573         char *name;
6574         int i;
6575
6576         status = torture_createdel_recv(subreq);
6577         if (!NT_STATUS_IS_OK(status)){
6578                 DEBUG(10, ("torture_createdel_recv returned %s\n",
6579                            nt_errstr(status)));
6580                 TALLOC_FREE(subreq);
6581                 tevent_req_nterror(req, status);
6582                 return;
6583         }
6584
6585         for (i=0; i<num_parallel; i++) {
6586                 if (subreq == state->reqs[i]) {
6587                         break;
6588                 }
6589         }
6590         if (i == num_parallel) {
6591                 DEBUG(10, ("received something we did not send\n"));
6592                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
6593                 return;
6594         }
6595         TALLOC_FREE(state->reqs[i]);
6596
6597         if (state->sent >= state->num_files) {
6598                 tevent_req_done(req);
6599                 return;
6600         }
6601
6602         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6603                                state->sent);
6604         if (tevent_req_nomem(name, req)) {
6605                 return;
6606         }
6607         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
6608                                                 state->cli, name);
6609         if (tevent_req_nomem(state->reqs[i], req)) {
6610                 return;
6611         }
6612         name = talloc_move(state->reqs[i], &name);
6613         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
6614         state->sent += 1;
6615 }
6616
6617 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
6618 {
6619         return tevent_req_simple_recv_ntstatus(req);
6620 }
6621
6622 struct swallow_notify_state {
6623         struct tevent_context *ev;
6624         struct cli_state *cli;
6625         uint16_t fnum;
6626         uint32_t completion_filter;
6627         bool recursive;
6628         bool (*fn)(uint32_t action, const char *name, void *priv);
6629         void *priv;
6630 };
6631
6632 static void swallow_notify_done(struct tevent_req *subreq);
6633
6634 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
6635                                               struct tevent_context *ev,
6636                                               struct cli_state *cli,
6637                                               uint16_t fnum,
6638                                               uint32_t completion_filter,
6639                                               bool recursive,
6640                                               bool (*fn)(uint32_t action,
6641                                                          const char *name,
6642                                                          void *priv),
6643                                               void *priv)
6644 {
6645         struct tevent_req *req, *subreq;
6646         struct swallow_notify_state *state;
6647
6648         req = tevent_req_create(mem_ctx, &state,
6649                                 struct swallow_notify_state);
6650         if (req == NULL) {
6651                 return NULL;
6652         }
6653         state->ev = ev;
6654         state->cli = cli;
6655         state->fnum = fnum;
6656         state->completion_filter = completion_filter;
6657         state->recursive = recursive;
6658         state->fn = fn;
6659         state->priv = priv;
6660
6661         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6662                                  0xffff, state->completion_filter,
6663                                  state->recursive);
6664         if (tevent_req_nomem(subreq, req)) {
6665                 return tevent_req_post(req, ev);
6666         }
6667         tevent_req_set_callback(subreq, swallow_notify_done, req);
6668         return req;
6669 }
6670
6671 static void swallow_notify_done(struct tevent_req *subreq)
6672 {
6673         struct tevent_req *req = tevent_req_callback_data(
6674                 subreq, struct tevent_req);
6675         struct swallow_notify_state *state = tevent_req_data(
6676                 req, struct swallow_notify_state);
6677         NTSTATUS status;
6678         uint32_t i, num_changes;
6679         struct notify_change *changes;
6680
6681         status = cli_notify_recv(subreq, state, &num_changes, &changes);
6682         TALLOC_FREE(subreq);
6683         if (!NT_STATUS_IS_OK(status)) {
6684                 DEBUG(10, ("cli_notify_recv returned %s\n",
6685                            nt_errstr(status)));
6686                 tevent_req_nterror(req, status);
6687                 return;
6688         }
6689
6690         for (i=0; i<num_changes; i++) {
6691                 state->fn(changes[i].action, changes[i].name, state->priv);
6692         }
6693         TALLOC_FREE(changes);
6694
6695         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6696                                  0xffff, state->completion_filter,
6697                                  state->recursive);
6698         if (tevent_req_nomem(subreq, req)) {
6699                 return;
6700         }
6701         tevent_req_set_callback(subreq, swallow_notify_done, req);
6702 }
6703
6704 static bool print_notifies(uint32_t action, const char *name, void *priv)
6705 {
6706         if (DEBUGLEVEL > 5) {
6707                 d_printf("%d %s\n", (int)action, name);
6708         }
6709         return true;
6710 }
6711
6712 static void notify_bench_done(struct tevent_req *req)
6713 {
6714         int *num_finished = (int *)tevent_req_callback_data_void(req);
6715         *num_finished += 1;
6716 }
6717
6718 static bool run_notify_bench(int dummy)
6719 {
6720         const char *dname = "\\notify-bench";
6721         struct tevent_context *ev;
6722         NTSTATUS status;
6723         uint16_t dnum;
6724         struct tevent_req *req1;
6725         struct tevent_req *req2 = NULL;
6726         int i, num_unc_names;
6727         int num_finished = 0;
6728
6729         printf("starting notify-bench test\n");
6730
6731         if (use_multishare_conn) {
6732                 char **unc_list;
6733                 unc_list = file_lines_load(multishare_conn_fname,
6734                                            &num_unc_names, 0, NULL);
6735                 if (!unc_list || num_unc_names <= 0) {
6736                         d_printf("Failed to load unc names list from '%s'\n",
6737                                  multishare_conn_fname);
6738                         return false;
6739                 }
6740                 TALLOC_FREE(unc_list);
6741         } else {
6742                 num_unc_names = 1;
6743         }
6744
6745         ev = tevent_context_init(talloc_tos());
6746         if (ev == NULL) {
6747                 d_printf("tevent_context_init failed\n");
6748                 return false;
6749         }
6750
6751         for (i=0; i<num_unc_names; i++) {
6752                 struct cli_state *cli;
6753                 char *base_fname;
6754
6755                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
6756                                              dname, i);
6757                 if (base_fname == NULL) {
6758                         return false;
6759                 }
6760
6761                 if (!torture_open_connection(&cli, i)) {
6762                         return false;
6763                 }
6764
6765                 status = cli_ntcreate(cli, dname, 0,
6766                                       MAXIMUM_ALLOWED_ACCESS,
6767                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
6768                                       FILE_SHARE_DELETE,
6769                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
6770                                       &dnum);
6771
6772                 if (!NT_STATUS_IS_OK(status)) {
6773                         d_printf("Could not create %s: %s\n", dname,
6774                                  nt_errstr(status));
6775                         return false;
6776                 }
6777
6778                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
6779                                            FILE_NOTIFY_CHANGE_FILE_NAME |
6780                                            FILE_NOTIFY_CHANGE_DIR_NAME |
6781                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
6782                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
6783                                            false, print_notifies, NULL);
6784                 if (req1 == NULL) {
6785                         d_printf("Could not create notify request\n");
6786                         return false;
6787                 }
6788
6789                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
6790                                                base_fname, 10, torture_numops);
6791                 if (req2 == NULL) {
6792                         d_printf("Could not create createdels request\n");
6793                         return false;
6794                 }
6795                 TALLOC_FREE(base_fname);
6796
6797                 tevent_req_set_callback(req2, notify_bench_done,
6798                                         &num_finished);
6799         }
6800
6801         while (num_finished < num_unc_names) {
6802                 int ret;
6803                 ret = tevent_loop_once(ev);
6804                 if (ret != 0) {
6805                         d_printf("tevent_loop_once failed\n");
6806                         return false;
6807                 }
6808         }
6809
6810         if (!tevent_req_poll(req2, ev)) {
6811                 d_printf("tevent_req_poll failed\n");
6812         }
6813
6814         status = torture_createdels_recv(req2);
6815         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
6816
6817         return true;
6818 }
6819
6820 static bool run_mangle1(int dummy)
6821 {
6822         struct cli_state *cli;
6823         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
6824         uint16_t fnum;
6825         fstring alt_name;
6826         NTSTATUS status;
6827         time_t change_time, access_time, write_time;
6828         SMB_OFF_T size;
6829         uint16_t mode;
6830
6831         printf("starting mangle1 test\n");
6832         if (!torture_open_connection(&cli, 0)) {
6833                 return False;
6834         }
6835
6836         cli_sockopt(cli, sockops);
6837
6838         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6839                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6840                               0, 0, &fnum);
6841         if (!NT_STATUS_IS_OK(status)) {
6842                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6843                 return false;
6844         }
6845         cli_close(cli, fnum);
6846
6847         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
6848         if (!NT_STATUS_IS_OK(status)) {
6849                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
6850                          nt_errstr(status));
6851                 return false;
6852         }
6853         d_printf("alt_name: %s\n", alt_name);
6854
6855         status = cli_open(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
6856         if (!NT_STATUS_IS_OK(status)) {
6857                 d_printf("cli_open(%s) failed: %s\n", alt_name,
6858                          nt_errstr(status));
6859                 return false;
6860         }
6861         cli_close(cli, fnum);
6862
6863         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
6864                                 &write_time, &size, &mode);
6865         if (!NT_STATUS_IS_OK(status)) {
6866                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
6867                          nt_errstr(status));
6868                 return false;
6869         }
6870
6871         return true;
6872 }
6873
6874 static size_t null_source(uint8_t *buf, size_t n, void *priv)
6875 {
6876         size_t *to_pull = (size_t *)priv;
6877         size_t thistime = *to_pull;
6878
6879         thistime = MIN(thistime, n);
6880         if (thistime == 0) {
6881                 return 0;
6882         }
6883
6884         memset(buf, 0, thistime);
6885         *to_pull -= thistime;
6886         return thistime;
6887 }
6888
6889 static bool run_windows_write(int dummy)
6890 {
6891         struct cli_state *cli1;
6892         uint16_t fnum;
6893         int i;
6894         bool ret = false;
6895         const char *fname = "\\writetest.txt";
6896         struct timeval start_time;
6897         double seconds;
6898         double kbytes;
6899         NTSTATUS status;
6900
6901         printf("starting windows_write test\n");
6902         if (!torture_open_connection(&cli1, 0)) {
6903                 return False;
6904         }
6905
6906         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6907         if (!NT_STATUS_IS_OK(status)) {
6908                 printf("open failed (%s)\n", nt_errstr(status));
6909                 return False;
6910         }
6911
6912         cli_sockopt(cli1, sockops);
6913
6914         start_time = timeval_current();
6915
6916         for (i=0; i<torture_numops; i++) {
6917                 uint8_t c = 0;
6918                 off_t start = i * torture_blocksize;
6919                 size_t to_pull = torture_blocksize - 1;
6920
6921                 status = cli_writeall(cli1, fnum, 0, &c,
6922                                       start + torture_blocksize - 1, 1, NULL);
6923                 if (!NT_STATUS_IS_OK(status)) {
6924                         printf("cli_write failed: %s\n", nt_errstr(status));
6925                         goto fail;
6926                 }
6927
6928                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
6929                                   null_source, &to_pull);
6930                 if (!NT_STATUS_IS_OK(status)) {
6931                         printf("cli_push returned: %s\n", nt_errstr(status));
6932                         goto fail;
6933                 }
6934         }
6935
6936         seconds = timeval_elapsed(&start_time);
6937         kbytes = (double)torture_blocksize * torture_numops;
6938         kbytes /= 1024;
6939
6940         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
6941                (double)seconds, (int)(kbytes/seconds));
6942
6943         ret = true;
6944  fail:
6945         cli_close(cli1, fnum);
6946         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6947         torture_close_connection(cli1);
6948         return ret;
6949 }
6950
6951 static bool run_cli_echo(int dummy)
6952 {
6953         struct cli_state *cli;
6954         NTSTATUS status;
6955
6956         printf("starting cli_echo test\n");
6957         if (!torture_open_connection(&cli, 0)) {
6958                 return false;
6959         }
6960         cli_sockopt(cli, sockops);
6961
6962         status = cli_echo(cli, 5, data_blob_const("hello", 5));
6963
6964         d_printf("cli_echo returned %s\n", nt_errstr(status));
6965
6966         torture_close_connection(cli);
6967         return NT_STATUS_IS_OK(status);
6968 }
6969
6970 static bool run_uid_regression_test(int dummy)
6971 {
6972         static struct cli_state *cli;
6973         int16_t old_vuid;
6974         int16_t old_cnum;
6975         bool correct = True;
6976         NTSTATUS status;
6977
6978         printf("starting uid regression test\n");
6979
6980         if (!torture_open_connection(&cli, 0)) {
6981                 return False;
6982         }
6983
6984         cli_sockopt(cli, sockops);
6985
6986         /* Ok - now save then logoff our current user. */
6987         old_vuid = cli->vuid;
6988
6989         status = cli_ulogoff(cli);
6990         if (!NT_STATUS_IS_OK(status)) {
6991                 d_printf("(%s) cli_ulogoff failed: %s\n",
6992                          __location__, nt_errstr(status));
6993                 correct = false;
6994                 goto out;
6995         }
6996
6997         cli->vuid = old_vuid;
6998
6999         /* Try an operation. */
7000         status = cli_mkdir(cli, "\\uid_reg_test");
7001         if (NT_STATUS_IS_OK(status)) {
7002                 d_printf("(%s) cli_mkdir succeeded\n",
7003                          __location__);
7004                 correct = false;
7005                 goto out;
7006         } else {
7007                 /* Should be bad uid. */
7008                 if (!check_error(__LINE__, cli, ERRSRV, ERRbaduid,
7009                                 NT_STATUS_USER_SESSION_DELETED)) {
7010                         correct = false;
7011                         goto out;
7012                 }
7013         }
7014
7015         old_cnum = cli->cnum;
7016
7017         /* Now try a SMBtdis with the invald vuid set to zero. */
7018         cli->vuid = 0;
7019
7020         /* This should succeed. */
7021         status = cli_tdis(cli);
7022
7023         if (NT_STATUS_IS_OK(status)) {
7024                 d_printf("First tdis with invalid vuid should succeed.\n");
7025         } else {
7026                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
7027                 correct = false;
7028                 goto out;
7029         }
7030
7031         cli->vuid = old_vuid;
7032         cli->cnum = old_cnum;
7033
7034         /* This should fail. */
7035         status = cli_tdis(cli);
7036         if (NT_STATUS_IS_OK(status)) {
7037                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
7038                 correct = false;
7039                 goto out;
7040         } else {
7041                 /* Should be bad tid. */
7042                 if (!check_error(__LINE__, cli, ERRSRV, ERRinvnid,
7043                                 NT_STATUS_NETWORK_NAME_DELETED)) {
7044                         correct = false;
7045                         goto out;
7046                 }
7047         }
7048
7049         cli_rmdir(cli, "\\uid_reg_test");
7050
7051   out:
7052
7053         cli_shutdown(cli);
7054         return correct;
7055 }
7056
7057
7058 static const char *illegal_chars = "*\\/?<>|\":";
7059 static char force_shortname_chars[] = " +,.[];=\177";
7060
7061 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
7062                              const char *mask, void *state)
7063 {
7064         struct cli_state *pcli = (struct cli_state *)state;
7065         fstring fname;
7066         NTSTATUS status = NT_STATUS_OK;
7067
7068         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
7069
7070         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7071                 return NT_STATUS_OK;
7072
7073         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7074                 status = cli_rmdir(pcli, fname);
7075                 if (!NT_STATUS_IS_OK(status)) {
7076                         printf("del_fn: failed to rmdir %s\n,", fname );
7077                 }
7078         } else {
7079                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7080                 if (!NT_STATUS_IS_OK(status)) {
7081                         printf("del_fn: failed to unlink %s\n,", fname );
7082                 }
7083         }
7084         return status;
7085 }
7086
7087 struct sn_state {
7088         int matched;
7089         int i;
7090         bool val;
7091 };
7092
7093 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
7094                               const char *name, void *state)
7095 {
7096         struct sn_state *s = (struct sn_state  *)state;
7097         int i = s->i;
7098
7099 #if 0
7100         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
7101                 i, finfo->name, finfo->short_name);
7102 #endif
7103
7104         if (strchr(force_shortname_chars, i)) {
7105                 if (!finfo->short_name[0]) {
7106                         /* Shortname not created when it should be. */
7107                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
7108                                 __location__, finfo->name, i);
7109                         s->val = true;
7110                 }
7111         } else if (finfo->short_name[0]){
7112                 /* Shortname created when it should not be. */
7113                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
7114                         __location__, finfo->short_name, finfo->name);
7115                 s->val = true;
7116         }
7117         s->matched += 1;
7118         return NT_STATUS_OK;
7119 }
7120
7121 static bool run_shortname_test(int dummy)
7122 {
7123         static struct cli_state *cli;
7124         bool correct = True;
7125         int i;
7126         struct sn_state s;
7127         char fname[20];
7128         NTSTATUS status;
7129
7130         printf("starting shortname test\n");
7131
7132         if (!torture_open_connection(&cli, 0)) {
7133                 return False;
7134         }
7135
7136         cli_sockopt(cli, sockops);
7137
7138         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7139         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7140         cli_rmdir(cli, "\\shortname");
7141
7142         status = cli_mkdir(cli, "\\shortname");
7143         if (!NT_STATUS_IS_OK(status)) {
7144                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
7145                         __location__, nt_errstr(status));
7146                 correct = false;
7147                 goto out;
7148         }
7149
7150         strlcpy(fname, "\\shortname\\", sizeof(fname));
7151         strlcat(fname, "test .txt", sizeof(fname));
7152
7153         s.val = false;
7154
7155         for (i = 32; i < 128; i++) {
7156                 uint16_t fnum = (uint16_t)-1;
7157
7158                 s.i = i;
7159
7160                 if (strchr(illegal_chars, i)) {
7161                         continue;
7162                 }
7163                 fname[15] = i;
7164
7165                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
7166                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
7167                 if (!NT_STATUS_IS_OK(status)) {
7168                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
7169                                 __location__, fname, nt_errstr(status));
7170                         correct = false;
7171                         goto out;
7172                 }
7173                 cli_close(cli, fnum);
7174
7175                 s.matched = 0;
7176                 cli_list(cli, "\\shortname\\test*.*", 0, shortname_list_fn,
7177                          &s);
7178                 if (s.matched != 1) {
7179                         d_printf("(%s) failed to list %s: %s\n",
7180                                 __location__, fname, cli_errstr(cli));
7181                         correct = false;
7182                         goto out;
7183                 }
7184
7185                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7186                 if (!NT_STATUS_IS_OK(status)) {
7187                         d_printf("(%s) failed to delete %s: %s\n",
7188                                 __location__, fname, nt_errstr(status));
7189                         correct = false;
7190                         goto out;
7191                 }
7192
7193                 if (s.val) {
7194                         correct = false;
7195                         goto out;
7196                 }
7197         }
7198
7199   out:
7200
7201         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7202         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7203         cli_rmdir(cli, "\\shortname");
7204         torture_close_connection(cli);
7205         return correct;
7206 }
7207
7208 static void pagedsearch_cb(struct tevent_req *req)
7209 {
7210         int rc;
7211         struct tldap_message *msg;
7212         char *dn;
7213
7214         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
7215         if (rc != TLDAP_SUCCESS) {
7216                 d_printf("tldap_search_paged_recv failed: %s\n",
7217                          tldap_err2string(rc));
7218                 return;
7219         }
7220         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
7221                 TALLOC_FREE(msg);
7222                 return;
7223         }
7224         if (!tldap_entry_dn(msg, &dn)) {
7225                 d_printf("tldap_entry_dn failed\n");
7226                 return;
7227         }
7228         d_printf("%s\n", dn);
7229         TALLOC_FREE(msg);
7230 }
7231
7232 static bool run_tldap(int dummy)
7233 {
7234         struct tldap_context *ld;
7235         int fd, rc;
7236         NTSTATUS status;
7237         struct sockaddr_storage addr;
7238         struct tevent_context *ev;
7239         struct tevent_req *req;
7240         char *basedn;
7241         const char *filter;
7242
7243         if (!resolve_name(host, &addr, 0, false)) {
7244                 d_printf("could not find host %s\n", host);
7245                 return false;
7246         }
7247         status = open_socket_out(&addr, 389, 9999, &fd);
7248         if (!NT_STATUS_IS_OK(status)) {
7249                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
7250                 return false;
7251         }
7252
7253         ld = tldap_context_create(talloc_tos(), fd);
7254         if (ld == NULL) {
7255                 close(fd);
7256                 d_printf("tldap_context_create failed\n");
7257                 return false;
7258         }
7259
7260         rc = tldap_fetch_rootdse(ld);
7261         if (rc != TLDAP_SUCCESS) {
7262                 d_printf("tldap_fetch_rootdse failed: %s\n",
7263                          tldap_errstr(talloc_tos(), ld, rc));
7264                 return false;
7265         }
7266
7267         basedn = tldap_talloc_single_attribute(
7268                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
7269         if (basedn == NULL) {
7270                 d_printf("no defaultNamingContext\n");
7271                 return false;
7272         }
7273         d_printf("defaultNamingContext: %s\n", basedn);
7274
7275         ev = tevent_context_init(talloc_tos());
7276         if (ev == NULL) {
7277                 d_printf("tevent_context_init failed\n");
7278                 return false;
7279         }
7280
7281         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
7282                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
7283                                       NULL, 0, 0,
7284                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
7285         if (req == NULL) {
7286                 d_printf("tldap_search_paged_send failed\n");
7287                 return false;
7288         }
7289         tevent_req_set_callback(req, pagedsearch_cb, NULL);
7290
7291         tevent_req_poll(req, ev);
7292
7293         TALLOC_FREE(req);
7294
7295         /* test search filters against rootDSE */
7296         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
7297                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
7298
7299         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
7300                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
7301                           talloc_tos(), NULL, NULL);
7302         if (rc != TLDAP_SUCCESS) {
7303                 d_printf("tldap_search with complex filter failed: %s\n",
7304                          tldap_errstr(talloc_tos(), ld, rc));
7305                 return false;
7306         }
7307
7308         TALLOC_FREE(ld);
7309         return true;
7310 }
7311
7312 /* Torture test to ensure no regression of :
7313 https://bugzilla.samba.org/show_bug.cgi?id=7084
7314 */
7315
7316 static bool run_dir_createtime(int dummy)
7317 {
7318         struct cli_state *cli;
7319         const char *dname = "\\testdir";
7320         const char *fname = "\\testdir\\testfile";
7321         NTSTATUS status;
7322         struct timespec create_time;
7323         struct timespec create_time1;
7324         uint16_t fnum;
7325         bool ret = false;
7326
7327         if (!torture_open_connection(&cli, 0)) {
7328                 return false;
7329         }
7330
7331         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7332         cli_rmdir(cli, dname);
7333
7334         status = cli_mkdir(cli, dname);
7335         if (!NT_STATUS_IS_OK(status)) {
7336                 printf("mkdir failed: %s\n", nt_errstr(status));
7337                 goto out;
7338         }
7339
7340         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
7341                                 NULL, NULL, NULL);
7342         if (!NT_STATUS_IS_OK(status)) {
7343                 printf("cli_qpathinfo2 returned %s\n",
7344                        nt_errstr(status));
7345                 goto out;
7346         }
7347
7348         /* Sleep 3 seconds, then create a file. */
7349         sleep(3);
7350
7351         status = cli_open(cli, fname, O_RDWR | O_CREAT | O_EXCL,
7352                          DENY_NONE, &fnum);
7353         if (!NT_STATUS_IS_OK(status)) {
7354                 printf("cli_open failed: %s\n", nt_errstr(status));
7355                 goto out;
7356         }
7357
7358         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
7359                                 NULL, NULL, NULL);
7360         if (!NT_STATUS_IS_OK(status)) {
7361                 printf("cli_qpathinfo2 (2) returned %s\n",
7362                        nt_errstr(status));
7363                 goto out;
7364         }
7365
7366         if (timespec_compare(&create_time1, &create_time)) {
7367                 printf("run_dir_createtime: create time was updated (error)\n");
7368         } else {
7369                 printf("run_dir_createtime: create time was not updated (correct)\n");
7370                 ret = true;
7371         }
7372
7373   out:
7374
7375         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7376         cli_rmdir(cli, dname);
7377         if (!torture_close_connection(cli)) {
7378                 ret = false;
7379         }
7380         return ret;
7381 }
7382
7383
7384 static bool run_streamerror(int dummy)
7385 {
7386         struct cli_state *cli;
7387         const char *dname = "\\testdir";
7388         const char *streamname =
7389                 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
7390         NTSTATUS status;
7391         time_t change_time, access_time, write_time;
7392         SMB_OFF_T size;
7393         uint16_t mode, fnum;
7394         bool ret = true;
7395
7396         if (!torture_open_connection(&cli, 0)) {
7397                 return false;
7398         }
7399
7400         cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7401         cli_rmdir(cli, dname);
7402
7403         status = cli_mkdir(cli, dname);
7404         if (!NT_STATUS_IS_OK(status)) {
7405                 printf("mkdir failed: %s\n", nt_errstr(status));
7406                 return false;
7407         }
7408
7409         cli_qpathinfo1(cli, streamname, &change_time, &access_time, &write_time,
7410                       &size, &mode);
7411         status = cli_nt_error(cli);
7412
7413         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7414                 printf("pathinfo returned %s, expected "
7415                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7416                        nt_errstr(status));
7417                 ret = false;
7418         }
7419
7420         status = cli_ntcreate(cli, streamname, 0x16,
7421                               FILE_READ_DATA|FILE_READ_EA|
7422                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
7423                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7424                               FILE_OPEN, 0, 0, &fnum);
7425
7426         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7427                 printf("ntcreate returned %s, expected "
7428                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7429                        nt_errstr(status));
7430                 ret = false;
7431         }
7432
7433
7434         cli_rmdir(cli, dname);
7435         return ret;
7436 }
7437
7438 static bool run_local_substitute(int dummy)
7439 {
7440         bool ok = true;
7441
7442         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
7443         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
7444         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
7445         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
7446         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
7447         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
7448         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
7449         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
7450
7451         /* Different captialization rules in sub_basic... */
7452
7453         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
7454                        "blaDOM") == 0);
7455
7456         return ok;
7457 }
7458
7459 static bool run_local_base64(int dummy)
7460 {
7461         int i;
7462         bool ret = true;
7463
7464         for (i=1; i<2000; i++) {
7465                 DATA_BLOB blob1, blob2;
7466                 char *b64;
7467
7468                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
7469                 blob1.length = i;
7470                 generate_random_buffer(blob1.data, blob1.length);
7471
7472                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
7473                 if (b64 == NULL) {
7474                         d_fprintf(stderr, "base64_encode_data_blob failed "
7475                                   "for %d bytes\n", i);
7476                         ret = false;
7477                 }
7478                 blob2 = base64_decode_data_blob(b64);
7479                 TALLOC_FREE(b64);
7480
7481                 if (data_blob_cmp(&blob1, &blob2)) {
7482                         d_fprintf(stderr, "data_blob_cmp failed for %d "
7483                                   "bytes\n", i);
7484                         ret = false;
7485                 }
7486                 TALLOC_FREE(blob1.data);
7487                 data_blob_free(&blob2);
7488         }
7489         return ret;
7490 }
7491
7492 static bool run_local_gencache(int dummy)
7493 {
7494         char *val;
7495         time_t tm;
7496         DATA_BLOB blob;
7497
7498         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
7499                 d_printf("%s: gencache_set() failed\n", __location__);
7500                 return False;
7501         }
7502
7503         if (!gencache_get("foo", NULL, NULL)) {
7504                 d_printf("%s: gencache_get() failed\n", __location__);
7505                 return False;
7506         }
7507
7508         if (!gencache_get("foo", &val, &tm)) {
7509                 d_printf("%s: gencache_get() failed\n", __location__);
7510                 return False;
7511         }
7512
7513         if (strcmp(val, "bar") != 0) {
7514                 d_printf("%s: gencache_get() returned %s, expected %s\n",
7515                          __location__, val, "bar");
7516                 SAFE_FREE(val);
7517                 return False;
7518         }
7519
7520         SAFE_FREE(val);
7521
7522         if (!gencache_del("foo")) {
7523                 d_printf("%s: gencache_del() failed\n", __location__);
7524                 return False;
7525         }
7526         if (gencache_del("foo")) {
7527                 d_printf("%s: second gencache_del() succeeded\n",
7528                          __location__);
7529                 return False;
7530         }
7531
7532         if (gencache_get("foo", &val, &tm)) {
7533                 d_printf("%s: gencache_get() on deleted entry "
7534                          "succeeded\n", __location__);
7535                 return False;
7536         }
7537
7538         blob = data_blob_string_const_null("bar");
7539         tm = time(NULL) + 60;
7540
7541         if (!gencache_set_data_blob("foo", &blob, tm)) {
7542                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
7543                 return False;
7544         }
7545
7546         if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7547                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
7548                 return False;
7549         }
7550
7551         if (strcmp((const char *)blob.data, "bar") != 0) {
7552                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
7553                          __location__, (const char *)blob.data, "bar");
7554                 data_blob_free(&blob);
7555                 return False;
7556         }
7557
7558         data_blob_free(&blob);
7559
7560         if (!gencache_del("foo")) {
7561                 d_printf("%s: gencache_del() failed\n", __location__);
7562                 return False;
7563         }
7564         if (gencache_del("foo")) {
7565                 d_printf("%s: second gencache_del() succeeded\n",
7566                          __location__);
7567                 return False;
7568         }
7569
7570         if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7571                 d_printf("%s: gencache_get_data_blob() on deleted entry "
7572                          "succeeded\n", __location__);
7573                 return False;
7574         }
7575
7576         return True;
7577 }
7578
7579 static bool rbt_testval(struct db_context *db, const char *key,
7580                         const char *value)
7581 {
7582         struct db_record *rec;
7583         TDB_DATA data = string_tdb_data(value);
7584         bool ret = false;
7585         NTSTATUS status;
7586
7587         rec = db->fetch_locked(db, db, string_tdb_data(key));
7588         if (rec == NULL) {
7589                 d_fprintf(stderr, "fetch_locked failed\n");
7590                 goto done;
7591         }
7592         status = rec->store(rec, data, 0);
7593         if (!NT_STATUS_IS_OK(status)) {
7594                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
7595                 goto done;
7596         }
7597         TALLOC_FREE(rec);
7598
7599         rec = db->fetch_locked(db, db, string_tdb_data(key));
7600         if (rec == NULL) {
7601                 d_fprintf(stderr, "second fetch_locked failed\n");
7602                 goto done;
7603         }
7604         if ((rec->value.dsize != data.dsize)
7605             || (memcmp(rec->value.dptr, data.dptr, data.dsize) != 0)) {
7606                 d_fprintf(stderr, "Got wrong data back\n");
7607                 goto done;
7608         }
7609
7610         ret = true;
7611  done:
7612         TALLOC_FREE(rec);
7613         return ret;
7614 }
7615
7616 static bool run_local_rbtree(int dummy)
7617 {
7618         struct db_context *db;
7619         bool ret = false;
7620         int i;
7621
7622         db = db_open_rbt(NULL);
7623
7624         if (db == NULL) {
7625                 d_fprintf(stderr, "db_open_rbt failed\n");
7626                 return false;
7627         }
7628
7629         for (i=0; i<1000; i++) {
7630                 char *key, *value;
7631
7632                 if (asprintf(&key, "key%ld", random()) == -1) {
7633                         goto done;
7634                 }
7635                 if (asprintf(&value, "value%ld", random()) == -1) {
7636                         SAFE_FREE(key);
7637                         goto done;
7638                 }
7639
7640                 if (!rbt_testval(db, key, value)) {
7641                         SAFE_FREE(key);
7642                         SAFE_FREE(value);
7643                         goto done;
7644                 }
7645
7646                 SAFE_FREE(value);
7647                 if (asprintf(&value, "value%ld", random()) == -1) {
7648                         SAFE_FREE(key);
7649                         goto done;
7650                 }
7651
7652                 if (!rbt_testval(db, key, value)) {
7653                         SAFE_FREE(key);
7654                         SAFE_FREE(value);
7655                         goto done;
7656                 }
7657
7658                 SAFE_FREE(key);
7659                 SAFE_FREE(value);
7660         }
7661
7662         ret = true;
7663
7664  done:
7665         TALLOC_FREE(db);
7666         return ret;
7667 }
7668
7669
7670 /*
7671   local test for character set functions
7672
7673   This is a very simple test for the functionality in convert_string_error()
7674  */
7675 static bool run_local_convert_string(int dummy)
7676 {
7677         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
7678         const char *test_strings[2] = { "March", "M\303\244rz" };
7679         char dst[7];
7680         int i;
7681
7682         for (i=0; i<2; i++) {
7683                 const char *str = test_strings[i];
7684                 int len = strlen(str);
7685                 size_t converted_size;
7686                 bool ret;
7687
7688                 memset(dst, 'X', sizeof(dst));
7689
7690                 /* first try with real source length */
7691                 ret = convert_string_error(CH_UNIX, CH_UTF8,
7692                                            str, len,
7693                                            dst, sizeof(dst),
7694                                            &converted_size);
7695                 if (ret != true) {
7696                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7697                         goto failed;
7698                 }
7699
7700                 if (converted_size != len) {
7701                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7702                                   str, len, (int)converted_size);
7703                         goto failed;
7704                 }
7705
7706                 if (strncmp(str, dst, converted_size) != 0) {
7707                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7708                         goto failed;
7709                 }
7710
7711                 if (strlen(str) != converted_size) {
7712                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7713                                   (int)strlen(str), (int)converted_size);
7714                         goto failed;
7715                 }
7716
7717                 if (dst[converted_size] != 'X') {
7718                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7719                         goto failed;
7720                 }
7721
7722                 /* now with srclen==-1, this causes the nul to be
7723                  * converted too */
7724                 ret = convert_string_error(CH_UNIX, CH_UTF8,
7725                                            str, -1,
7726                                            dst, sizeof(dst),
7727                                            &converted_size);
7728                 if (ret != true) {
7729                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7730                         goto failed;
7731                 }
7732
7733                 if (converted_size != len+1) {
7734                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7735                                   str, len, (int)converted_size);
7736                         goto failed;
7737                 }
7738
7739                 if (strncmp(str, dst, converted_size) != 0) {
7740                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7741                         goto failed;
7742                 }
7743
7744                 if (len+1 != converted_size) {
7745                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7746                                   len+1, (int)converted_size);
7747                         goto failed;
7748                 }
7749
7750                 if (dst[converted_size] != 'X') {
7751                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7752                         goto failed;
7753                 }
7754
7755         }
7756
7757
7758         TALLOC_FREE(tmp_ctx);
7759         return true;
7760 failed:
7761         TALLOC_FREE(tmp_ctx);
7762         return false;
7763 }
7764
7765
7766 struct talloc_dict_test {
7767         int content;
7768 };
7769
7770 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
7771 {
7772         int *count = (int *)priv;
7773         *count += 1;
7774         return 0;
7775 }
7776
7777 static bool run_local_talloc_dict(int dummy)
7778 {
7779         struct talloc_dict *dict;
7780         struct talloc_dict_test *t;
7781         int key, count;
7782
7783         dict = talloc_dict_init(talloc_tos());
7784         if (dict == NULL) {
7785                 return false;
7786         }
7787
7788         t = talloc(talloc_tos(), struct talloc_dict_test);
7789         if (t == NULL) {
7790                 return false;
7791         }
7792
7793         key = 1;
7794         t->content = 1;
7795         if (!talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), t)) {
7796                 return false;
7797         }
7798
7799         count = 0;
7800         if (talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count) != 0) {
7801                 return false;
7802         }
7803
7804         if (count != 1) {
7805                 return false;
7806         }
7807
7808         TALLOC_FREE(dict);
7809
7810         return true;
7811 }
7812
7813 static bool run_local_string_to_sid(int dummy) {
7814         struct dom_sid sid;
7815
7816         if (string_to_sid(&sid, "S--1-5-32-545")) {
7817                 printf("allowing S--1-5-32-545\n");
7818                 return false;
7819         }
7820         if (string_to_sid(&sid, "S-1-5-32-+545")) {
7821                 printf("allowing S-1-5-32-+545\n");
7822                 return false;
7823         }
7824         if (string_to_sid(&sid, "S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0")) {
7825                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
7826                 return false;
7827         }
7828         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
7829                 printf("allowing S-1-5-32-545-abc\n");
7830                 return false;
7831         }
7832         if (!string_to_sid(&sid, "S-1-5-32-545")) {
7833                 printf("could not parse S-1-5-32-545\n");
7834                 return false;
7835         }
7836         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
7837                 printf("mis-parsed S-1-5-32-545 as %s\n",
7838                        sid_string_tos(&sid));
7839                 return false;
7840         }
7841         return true;
7842 }
7843
7844 static bool run_local_binary_to_sid(int dummy) {
7845         struct dom_sid *sid = talloc(NULL, struct dom_sid);
7846         static const char good_binary_sid[] = {
7847                 0x1, /* revision number */
7848                 15, /* num auths */
7849                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7850                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7851                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7852                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7853                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7854                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7855                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7856                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7857                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7858                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7859                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7860                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7861                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7862                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7863                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7864                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7865         };
7866
7867         static const char long_binary_sid[] = {
7868                 0x1, /* revision number */
7869                 15, /* num auths */
7870                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7871                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7872                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7873                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7874                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7875                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7876                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7877                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7878                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7879                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7880                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7881                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7882                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7883                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7884                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7885                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7886                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
7887                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
7888                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
7889         };
7890
7891         static const char long_binary_sid2[] = {
7892                 0x1, /* revision number */
7893                 32, /* num auths */
7894                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7895                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7896                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7897                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7898                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7899                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7900                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7901                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7902                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7903                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7904                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7905                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7906                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7907                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7908                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7909                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7910                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
7911                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
7912                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
7913                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
7914                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
7915                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
7916                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
7917                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
7918                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
7919                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
7920                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
7921                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
7922                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
7923                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
7924                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
7925                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
7926                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
7927         };
7928
7929         if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
7930                 return false;
7931         }
7932         if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
7933                 return false;
7934         }
7935         if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
7936                 return false;
7937         }
7938         return true;
7939 }
7940
7941 /* Split a path name into filename and stream name components. Canonicalise
7942  * such that an implicit $DATA token is always explicit.
7943  *
7944  * The "specification" of this function can be found in the
7945  * run_local_stream_name() function in torture.c, I've tried those
7946  * combinations against a W2k3 server.
7947  */
7948
7949 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
7950                                        char **pbase, char **pstream)
7951 {
7952         char *base = NULL;
7953         char *stream = NULL;
7954         char *sname; /* stream name */
7955         const char *stype; /* stream type */
7956
7957         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
7958
7959         sname = strchr_m(fname, ':');
7960
7961         if (lp_posix_pathnames() || (sname == NULL)) {
7962                 if (pbase != NULL) {
7963                         base = talloc_strdup(mem_ctx, fname);
7964                         NT_STATUS_HAVE_NO_MEMORY(base);
7965                 }
7966                 goto done;
7967         }
7968
7969         if (pbase != NULL) {
7970                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
7971                 NT_STATUS_HAVE_NO_MEMORY(base);
7972         }
7973
7974         sname += 1;
7975
7976         stype = strchr_m(sname, ':');
7977
7978         if (stype == NULL) {
7979                 sname = talloc_strdup(mem_ctx, sname);
7980                 stype = "$DATA";
7981         }
7982         else {
7983                 if (strcasecmp_m(stype, ":$DATA") != 0) {
7984                         /*
7985                          * If there is an explicit stream type, so far we only
7986                          * allow $DATA. Is there anything else allowed? -- vl
7987                          */
7988                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
7989                         TALLOC_FREE(base);
7990                         return NT_STATUS_OBJECT_NAME_INVALID;
7991                 }
7992                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
7993                 stype += 1;
7994         }
7995
7996         if (sname == NULL) {
7997                 TALLOC_FREE(base);
7998                 return NT_STATUS_NO_MEMORY;
7999         }
8000
8001         if (sname[0] == '\0') {
8002                 /*
8003                  * no stream name, so no stream
8004                  */
8005                 goto done;
8006         }
8007
8008         if (pstream != NULL) {
8009                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
8010                 if (stream == NULL) {
8011                         TALLOC_FREE(sname);
8012                         TALLOC_FREE(base);
8013                         return NT_STATUS_NO_MEMORY;
8014                 }
8015                 /*
8016                  * upper-case the type field
8017                  */
8018                 strupper_m(strchr_m(stream, ':')+1);
8019         }
8020
8021  done:
8022         if (pbase != NULL) {
8023                 *pbase = base;
8024         }
8025         if (pstream != NULL) {
8026                 *pstream = stream;
8027         }
8028         return NT_STATUS_OK;
8029 }
8030
8031 static bool test_stream_name(const char *fname, const char *expected_base,
8032                              const char *expected_stream,
8033                              NTSTATUS expected_status)
8034 {
8035         NTSTATUS status;
8036         char *base = NULL;
8037         char *stream = NULL;
8038
8039         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
8040         if (!NT_STATUS_EQUAL(status, expected_status)) {
8041                 goto error;
8042         }
8043
8044         if (!NT_STATUS_IS_OK(status)) {
8045                 return true;
8046         }
8047
8048         if (base == NULL) goto error;
8049
8050         if (strcmp(expected_base, base) != 0) goto error;
8051
8052         if ((expected_stream != NULL) && (stream == NULL)) goto error;
8053         if ((expected_stream == NULL) && (stream != NULL)) goto error;
8054
8055         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
8056                 goto error;
8057
8058         TALLOC_FREE(base);
8059         TALLOC_FREE(stream);
8060         return true;
8061
8062  error:
8063         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
8064                   fname, expected_base ? expected_base : "<NULL>",
8065                   expected_stream ? expected_stream : "<NULL>",
8066                   nt_errstr(expected_status));
8067         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
8068                   base ? base : "<NULL>", stream ? stream : "<NULL>",
8069                   nt_errstr(status));
8070         TALLOC_FREE(base);
8071         TALLOC_FREE(stream);
8072         return false;
8073 }
8074
8075 static bool run_local_stream_name(int dummy)
8076 {
8077         bool ret = true;
8078
8079         ret &= test_stream_name(
8080                 "bla", "bla", NULL, NT_STATUS_OK);
8081         ret &= test_stream_name(
8082                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
8083         ret &= test_stream_name(
8084                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8085         ret &= test_stream_name(
8086                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
8087         ret &= test_stream_name(
8088                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8089         ret &= test_stream_name(
8090                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
8091         ret &= test_stream_name(
8092                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
8093         ret &= test_stream_name(
8094                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
8095
8096         return ret;
8097 }
8098
8099 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
8100 {
8101         if (a.length != b.length) {
8102                 printf("a.length=%d != b.length=%d\n",
8103                        (int)a.length, (int)b.length);
8104                 return false;
8105         }
8106         if (memcmp(a.data, b.data, a.length) != 0) {
8107                 printf("a.data and b.data differ\n");
8108                 return false;
8109         }
8110         return true;
8111 }
8112
8113 static bool run_local_memcache(int dummy)
8114 {
8115         struct memcache *cache;
8116         DATA_BLOB k1, k2;
8117         DATA_BLOB d1, d2, d3;
8118         DATA_BLOB v1, v2, v3;
8119
8120         TALLOC_CTX *mem_ctx;
8121         char *str1, *str2;
8122         size_t size1, size2;
8123         bool ret = false;
8124
8125         cache = memcache_init(NULL, 100);
8126
8127         if (cache == NULL) {
8128                 printf("memcache_init failed\n");
8129                 return false;
8130         }
8131
8132         d1 = data_blob_const("d1", 2);
8133         d2 = data_blob_const("d2", 2);
8134         d3 = data_blob_const("d3", 2);
8135
8136         k1 = data_blob_const("d1", 2);
8137         k2 = data_blob_const("d2", 2);
8138
8139         memcache_add(cache, STAT_CACHE, k1, d1);
8140         memcache_add(cache, GETWD_CACHE, k2, d2);
8141
8142         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
8143                 printf("could not find k1\n");
8144                 return false;
8145         }
8146         if (!data_blob_equal(d1, v1)) {
8147                 return false;
8148         }
8149
8150         if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8151                 printf("could not find k2\n");
8152                 return false;
8153         }
8154         if (!data_blob_equal(d2, v2)) {
8155                 return false;
8156         }
8157
8158         memcache_add(cache, STAT_CACHE, k1, d3);
8159
8160         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
8161                 printf("could not find replaced k1\n");
8162                 return false;
8163         }
8164         if (!data_blob_equal(d3, v3)) {
8165                 return false;
8166         }
8167
8168         memcache_add(cache, GETWD_CACHE, k1, d1);
8169
8170         if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8171                 printf("Did find k2, should have been purged\n");
8172                 return false;
8173         }
8174
8175         TALLOC_FREE(cache);
8176
8177         cache = memcache_init(NULL, 0);
8178
8179         mem_ctx = talloc_init("foo");
8180
8181         str1 = talloc_strdup(mem_ctx, "string1");
8182         str2 = talloc_strdup(mem_ctx, "string2");
8183
8184         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8185                             data_blob_string_const("torture"), &str1);
8186         size1 = talloc_total_size(cache);
8187
8188         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8189                             data_blob_string_const("torture"), &str2);
8190         size2 = talloc_total_size(cache);
8191
8192         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
8193
8194         if (size2 > size1) {
8195                 printf("memcache leaks memory!\n");
8196                 goto fail;
8197         }
8198
8199         ret = true;
8200  fail:
8201         TALLOC_FREE(cache);
8202         return ret;
8203 }
8204
8205 static void wbclient_done(struct tevent_req *req)
8206 {
8207         wbcErr wbc_err;
8208         struct winbindd_response *wb_resp;
8209         int *i = (int *)tevent_req_callback_data_void(req);
8210
8211         wbc_err = wb_trans_recv(req, req, &wb_resp);
8212         TALLOC_FREE(req);
8213         *i += 1;
8214         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
8215 }
8216
8217 static bool run_local_wbclient(int dummy)
8218 {
8219         struct event_context *ev;
8220         struct wb_context **wb_ctx;
8221         struct winbindd_request wb_req;
8222         bool result = false;
8223         int i, j;
8224
8225         BlockSignals(True, SIGPIPE);
8226
8227         ev = tevent_context_init_byname(talloc_tos(), "epoll");
8228         if (ev == NULL) {
8229                 goto fail;
8230         }
8231
8232         wb_ctx = TALLOC_ARRAY(ev, struct wb_context *, nprocs);
8233         if (wb_ctx == NULL) {
8234                 goto fail;
8235         }
8236
8237         ZERO_STRUCT(wb_req);
8238         wb_req.cmd = WINBINDD_PING;
8239
8240         d_printf("nprocs=%d, numops=%d\n", (int)nprocs, (int)torture_numops);
8241
8242         for (i=0; i<nprocs; i++) {
8243                 wb_ctx[i] = wb_context_init(ev, NULL);
8244                 if (wb_ctx[i] == NULL) {
8245                         goto fail;
8246                 }
8247                 for (j=0; j<torture_numops; j++) {
8248                         struct tevent_req *req;
8249                         req = wb_trans_send(ev, ev, wb_ctx[i],
8250                                             (j % 2) == 0, &wb_req);
8251                         if (req == NULL) {
8252                                 goto fail;
8253                         }
8254                         tevent_req_set_callback(req, wbclient_done, &i);
8255                 }
8256         }
8257
8258         i = 0;
8259
8260         while (i < nprocs * torture_numops) {
8261                 event_loop_once(ev);
8262         }
8263
8264         result = true;
8265  fail:
8266         TALLOC_FREE(ev);
8267         return result;
8268 }
8269
8270 static void getaddrinfo_finished(struct tevent_req *req)
8271 {
8272         char *name = (char *)tevent_req_callback_data_void(req);
8273         struct addrinfo *ainfo;
8274         int res;
8275
8276         res = getaddrinfo_recv(req, &ainfo);
8277         if (res != 0) {
8278                 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
8279                 return;
8280         }
8281         d_printf("gai(%s) succeeded\n", name);
8282         freeaddrinfo(ainfo);
8283 }
8284
8285 static bool run_getaddrinfo_send(int dummy)
8286 {
8287         TALLOC_CTX *frame = talloc_stackframe();
8288         struct fncall_context *ctx;
8289         struct tevent_context *ev;
8290         bool result = false;
8291         const char *names[4] = { "www.samba.org", "notfound.samba.org",
8292                                  "www.slashdot.org", "heise.de" };
8293         struct tevent_req *reqs[4];
8294         int i;
8295
8296         ev = event_context_init(frame);
8297         if (ev == NULL) {
8298                 goto fail;
8299         }
8300
8301         ctx = fncall_context_init(frame, 4);
8302
8303         for (i=0; i<ARRAY_SIZE(names); i++) {
8304                 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
8305                                            NULL);
8306                 if (reqs[i] == NULL) {
8307                         goto fail;
8308                 }
8309                 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
8310                                         discard_const_p(void, names[i]));
8311         }
8312
8313         for (i=0; i<ARRAY_SIZE(reqs); i++) {
8314                 tevent_loop_once(ev);
8315         }
8316
8317         result = true;
8318 fail:
8319         TALLOC_FREE(frame);
8320         return result;
8321 }
8322
8323 static bool dbtrans_inc(struct db_context *db)
8324 {
8325         struct db_record *rec;
8326         uint32_t *val;
8327         bool ret = false;
8328         NTSTATUS status;
8329
8330         rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
8331         if (rec == NULL) {
8332                 printf(__location__ "fetch_lock failed\n");
8333                 return false;
8334         }
8335
8336         if (rec->value.dsize != sizeof(uint32_t)) {
8337                 printf(__location__ "value.dsize = %d\n",
8338                        (int)rec->value.dsize);
8339                 goto fail;
8340         }
8341
8342         val = (uint32_t *)rec->value.dptr;
8343         *val += 1;
8344
8345         status = rec->store(rec, make_tdb_data((uint8_t *)val,
8346                                                sizeof(uint32_t)),
8347                             0);
8348         if (!NT_STATUS_IS_OK(status)) {
8349                 printf(__location__ "store failed: %s\n",
8350                        nt_errstr(status));
8351                 goto fail;
8352         }
8353
8354         ret = true;
8355 fail:
8356         TALLOC_FREE(rec);
8357         return ret;
8358 }
8359
8360 static bool run_local_dbtrans(int dummy)
8361 {
8362         struct db_context *db;
8363         struct db_record *rec;
8364         NTSTATUS status;
8365         uint32_t initial;
8366         int res;
8367
8368         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
8369                      O_RDWR|O_CREAT, 0600);
8370         if (db == NULL) {
8371                 printf("Could not open transtest.db\n");
8372                 return false;
8373         }
8374
8375         res = db->transaction_start(db);
8376         if (res == -1) {
8377                 printf(__location__ "transaction_start failed\n");
8378                 return false;
8379         }
8380
8381         rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
8382         if (rec == NULL) {
8383                 printf(__location__ "fetch_lock failed\n");
8384                 return false;
8385         }
8386
8387         if (rec->value.dptr == NULL) {
8388                 initial = 0;
8389                 status = rec->store(
8390                         rec, make_tdb_data((uint8_t *)&initial,
8391                                            sizeof(initial)),
8392                         0);
8393                 if (!NT_STATUS_IS_OK(status)) {
8394                         printf(__location__ "store returned %s\n",
8395                                nt_errstr(status));
8396                         return false;
8397                 }
8398         }
8399
8400         TALLOC_FREE(rec);
8401
8402         res = db->transaction_commit(db);
8403         if (res == -1) {
8404                 printf(__location__ "transaction_commit failed\n");
8405                 return false;
8406         }
8407
8408         while (true) {
8409                 uint32_t val, val2;
8410                 int i;
8411
8412                 res = db->transaction_start(db);
8413                 if (res == -1) {
8414                         printf(__location__ "transaction_start failed\n");
8415                         break;
8416                 }
8417
8418                 if (!dbwrap_fetch_uint32(db, "transtest", &val)) {
8419                         printf(__location__ "dbwrap_fetch_uint32 failed\n");
8420                         break;
8421                 }
8422
8423                 for (i=0; i<10; i++) {
8424                         if (!dbtrans_inc(db)) {
8425                                 return false;
8426                         }
8427                 }
8428
8429                 if (!dbwrap_fetch_uint32(db, "transtest", &val2)) {
8430                         printf(__location__ "dbwrap_fetch_uint32 failed\n");
8431                         break;
8432                 }
8433
8434                 if (val2 != val + 10) {
8435                         printf(__location__ "val=%d, val2=%d\n",
8436                                (int)val, (int)val2);
8437                         break;
8438                 }
8439
8440                 printf("val2=%d\r", val2);
8441
8442                 res = db->transaction_commit(db);
8443                 if (res == -1) {
8444                         printf(__location__ "transaction_commit failed\n");
8445                         break;
8446                 }
8447         }
8448
8449         TALLOC_FREE(db);
8450         return true;
8451 }
8452
8453 /*
8454  * Just a dummy test to be run under a debugger. There's no real way
8455  * to inspect the tevent_select specific function from outside of
8456  * tevent_select.c.
8457  */
8458
8459 static bool run_local_tevent_select(int dummy)
8460 {
8461         struct tevent_context *ev;
8462         struct tevent_fd *fd1, *fd2;
8463         bool result = false;
8464
8465         ev = tevent_context_init_byname(NULL, "select");
8466         if (ev == NULL) {
8467                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
8468                 goto fail;
8469         }
8470
8471         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
8472         if (fd1 == NULL) {
8473                 d_fprintf(stderr, "tevent_add_fd failed\n");
8474                 goto fail;
8475         }
8476         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
8477         if (fd2 == NULL) {
8478                 d_fprintf(stderr, "tevent_add_fd failed\n");
8479                 goto fail;
8480         }
8481         TALLOC_FREE(fd2);
8482
8483         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
8484         if (fd2 == NULL) {
8485                 d_fprintf(stderr, "tevent_add_fd failed\n");
8486                 goto fail;
8487         }
8488
8489         result = true;
8490 fail:
8491         TALLOC_FREE(ev);
8492         return result;
8493 }
8494
8495 static double create_procs(bool (*fn)(int), bool *result)
8496 {
8497         int i, status;
8498         volatile pid_t *child_status;
8499         volatile bool *child_status_out;
8500         int synccount;
8501         int tries = 8;
8502         struct timeval start;
8503
8504         synccount = 0;
8505
8506         child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*nprocs);
8507         if (!child_status) {
8508                 printf("Failed to setup shared memory\n");
8509                 return -1;
8510         }
8511
8512         child_status_out = (volatile bool *)shm_setup(sizeof(bool)*nprocs);
8513         if (!child_status_out) {
8514                 printf("Failed to setup result status shared memory\n");
8515                 return -1;
8516         }
8517
8518         for (i = 0; i < nprocs; i++) {
8519                 child_status[i] = 0;
8520                 child_status_out[i] = True;
8521         }
8522
8523         start = timeval_current();
8524
8525         for (i=0;i<nprocs;i++) {
8526                 procnum = i;
8527                 if (fork() == 0) {
8528                         pid_t mypid = getpid();
8529                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
8530
8531                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
8532
8533                         while (1) {
8534                                 if (torture_open_connection(&current_cli, i)) break;
8535                                 if (tries-- == 0) {
8536                                         printf("pid %d failed to start\n", (int)getpid());
8537                                         _exit(1);
8538                                 }
8539                                 smb_msleep(10); 
8540                         }
8541
8542                         child_status[i] = getpid();
8543
8544                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
8545
8546                         child_status_out[i] = fn(i);
8547                         _exit(0);
8548                 }
8549         }
8550
8551         do {
8552                 synccount = 0;
8553                 for (i=0;i<nprocs;i++) {
8554                         if (child_status[i]) synccount++;
8555                 }
8556                 if (synccount == nprocs) break;
8557                 smb_msleep(10);
8558         } while (timeval_elapsed(&start) < 30);
8559
8560         if (synccount != nprocs) {
8561                 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
8562                 *result = False;
8563                 return timeval_elapsed(&start);
8564         }
8565
8566         /* start the client load */
8567         start = timeval_current();
8568
8569         for (i=0;i<nprocs;i++) {
8570                 child_status[i] = 0;
8571         }
8572
8573         printf("%d clients started\n", nprocs);
8574
8575         for (i=0;i<nprocs;i++) {
8576                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
8577         }
8578
8579         printf("\n");
8580
8581         for (i=0;i<nprocs;i++) {
8582                 if (!child_status_out[i]) {
8583                         *result = False;
8584                 }
8585         }
8586         return timeval_elapsed(&start);
8587 }
8588
8589 #define FLAG_MULTIPROC 1
8590
8591 static struct {
8592         const char *name;
8593         bool (*fn)(int);
8594         unsigned flags;
8595 } torture_ops[] = {
8596         {"FDPASS", run_fdpasstest, 0},
8597         {"LOCK1",  run_locktest1,  0},
8598         {"LOCK2",  run_locktest2,  0},
8599         {"LOCK3",  run_locktest3,  0},
8600         {"LOCK4",  run_locktest4,  0},
8601         {"LOCK5",  run_locktest5,  0},
8602         {"LOCK6",  run_locktest6,  0},
8603         {"LOCK7",  run_locktest7,  0},
8604         {"LOCK8",  run_locktest8,  0},
8605         {"LOCK9",  run_locktest9,  0},
8606         {"UNLINK", run_unlinktest, 0},
8607         {"BROWSE", run_browsetest, 0},
8608         {"ATTR",   run_attrtest,   0},
8609         {"TRANS2", run_trans2test, 0},
8610         {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
8611         {"TORTURE",run_torture,    FLAG_MULTIPROC},
8612         {"RANDOMIPC", run_randomipc, 0},
8613         {"NEGNOWAIT", run_negprot_nowait, 0},
8614         {"NBENCH",  run_nbench, 0},
8615         {"NBENCH2", run_nbench2, 0},
8616         {"OPLOCK1",  run_oplock1, 0},
8617         {"OPLOCK2",  run_oplock2, 0},
8618         {"OPLOCK3",  run_oplock3, 0},
8619         {"OPLOCK4",  run_oplock4, 0},
8620         {"DIR",  run_dirtest, 0},
8621         {"DIR1",  run_dirtest1, 0},
8622         {"DIR-CREATETIME",  run_dir_createtime, 0},
8623         {"DENY1",  torture_denytest1, 0},
8624         {"DENY2",  torture_denytest2, 0},
8625         {"TCON",  run_tcon_test, 0},
8626         {"TCONDEV",  run_tcon_devtype_test, 0},
8627         {"RW1",  run_readwritetest, 0},
8628         {"RW2",  run_readwritemulti, FLAG_MULTIPROC},
8629         {"RW3",  run_readwritelarge, 0},
8630         {"RW-SIGNING",  run_readwritelarge_signtest, 0},
8631         {"OPEN", run_opentest, 0},
8632         {"POSIX", run_simple_posix_open_test, 0},
8633         {"POSIX-APPEND", run_posix_append, 0},
8634         {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
8635         {"ASYNC-ECHO", run_async_echo, 0},
8636         { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
8637         { "SHORTNAME-TEST", run_shortname_test, 0},
8638         { "ADDRCHANGE", run_addrchange, 0},
8639 #if 1
8640         {"OPENATTR", run_openattrtest, 0},
8641 #endif
8642         {"XCOPY", run_xcopy, 0},
8643         {"RENAME", run_rename, 0},
8644         {"DELETE", run_deletetest, 0},
8645         {"DELETE-LN", run_deletetest_ln, 0},
8646         {"PROPERTIES", run_properties, 0},
8647         {"MANGLE", torture_mangle, 0},
8648         {"MANGLE1", run_mangle1, 0},
8649         {"W2K", run_w2ktest, 0},
8650         {"TRANS2SCAN", torture_trans2_scan, 0},
8651         {"NTTRANSSCAN", torture_nttrans_scan, 0},
8652         {"UTABLE", torture_utable, 0},
8653         {"CASETABLE", torture_casetable, 0},
8654         {"ERRMAPEXTRACT", run_error_map_extract, 0},
8655         {"PIPE_NUMBER", run_pipe_number, 0},
8656         {"TCON2",  run_tcon2_test, 0},
8657         {"IOCTL",  torture_ioctl_test, 0},
8658         {"CHKPATH",  torture_chkpath_test, 0},
8659         {"FDSESS", run_fdsesstest, 0},
8660         { "EATEST", run_eatest, 0},
8661         { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
8662         { "CHAIN1", run_chain1, 0},
8663         { "CHAIN2", run_chain2, 0},
8664         { "WINDOWS-WRITE", run_windows_write, 0},
8665         { "CLI_ECHO", run_cli_echo, 0},
8666         { "GETADDRINFO", run_getaddrinfo_send, 0},
8667         { "TLDAP", run_tldap },
8668         { "STREAMERROR", run_streamerror },
8669         { "NOTIFY-BENCH", run_notify_bench },
8670         { "BAD-NBT-SESSION", run_bad_nbt_session },
8671         { "SMB-ANY-CONNECT", run_smb_any_connect },
8672         { "NOTIFY-ONLINE", run_notify_online },
8673         { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
8674         { "LOCAL-GENCACHE", run_local_gencache, 0},
8675         { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
8676         { "LOCAL-BASE64", run_local_base64, 0},
8677         { "LOCAL-RBTREE", run_local_rbtree, 0},
8678         { "LOCAL-MEMCACHE", run_local_memcache, 0},
8679         { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
8680         { "LOCAL-WBCLIENT", run_local_wbclient, 0},
8681         { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
8682         { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
8683         { "LOCAL-DBTRANS", run_local_dbtrans, 0},
8684         { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
8685         { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
8686         {NULL, NULL, 0}};
8687
8688
8689
8690 /****************************************************************************
8691 run a specified test or "ALL"
8692 ****************************************************************************/
8693 static bool run_test(const char *name)
8694 {
8695         bool ret = True;
8696         bool result = True;
8697         bool found = False;
8698         int i;
8699         double t;
8700         if (strequal(name,"ALL")) {
8701                 for (i=0;torture_ops[i].name;i++) {
8702                         run_test(torture_ops[i].name);
8703                 }
8704                 found = True;
8705         }
8706
8707         for (i=0;torture_ops[i].name;i++) {
8708                 fstr_sprintf(randomfname, "\\XX%x", 
8709                          (unsigned)random());
8710
8711                 if (strequal(name, torture_ops[i].name)) {
8712                         found = True;
8713                         printf("Running %s\n", name);
8714                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
8715                                 t = create_procs(torture_ops[i].fn, &result);
8716                                 if (!result) { 
8717                                         ret = False;
8718                                         printf("TEST %s FAILED!\n", name);
8719                                 }
8720                         } else {
8721                                 struct timeval start;
8722                                 start = timeval_current();
8723                                 if (!torture_ops[i].fn(0)) {
8724                                         ret = False;
8725                                         printf("TEST %s FAILED!\n", name);
8726                                 }
8727                                 t = timeval_elapsed(&start);
8728                         }
8729                         printf("%s took %g secs\n\n", name, t);
8730                 }
8731         }
8732
8733         if (!found) {
8734                 printf("Did not find a test named %s\n", name);
8735                 ret = False;
8736         }
8737
8738         return ret;
8739 }
8740
8741
8742 static void usage(void)
8743 {
8744         int i;
8745
8746         printf("WARNING samba4 test suite is much more complete nowadays.\n");
8747         printf("Please use samba4 torture.\n\n");
8748
8749         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
8750
8751         printf("\t-d debuglevel\n");
8752         printf("\t-U user%%pass\n");
8753         printf("\t-k               use kerberos\n");
8754         printf("\t-N numprocs\n");
8755         printf("\t-n my_netbios_name\n");
8756         printf("\t-W workgroup\n");
8757         printf("\t-o num_operations\n");
8758         printf("\t-O socket_options\n");
8759         printf("\t-m maximum protocol\n");
8760         printf("\t-L use oplocks\n");
8761         printf("\t-c CLIENT.TXT   specify client load file for NBENCH\n");
8762         printf("\t-A showall\n");
8763         printf("\t-p port\n");
8764         printf("\t-s seed\n");
8765         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
8766         printf("\t-f filename   filename to test\n");
8767         printf("\n\n");
8768
8769         printf("tests are:");
8770         for (i=0;torture_ops[i].name;i++) {
8771                 printf(" %s", torture_ops[i].name);
8772         }
8773         printf("\n");
8774
8775         printf("default test is ALL\n");
8776
8777         exit(1);
8778 }
8779
8780 /****************************************************************************
8781   main program
8782 ****************************************************************************/
8783  int main(int argc,char *argv[])
8784 {
8785         int opt, i;
8786         char *p;
8787         int gotuser = 0;
8788         int gotpass = 0;
8789         bool correct = True;
8790         TALLOC_CTX *frame = talloc_stackframe();
8791         int seed = time(NULL);
8792
8793 #ifdef HAVE_SETBUFFER
8794         setbuffer(stdout, NULL, 0);
8795 #endif
8796
8797         setup_logging("smbtorture", DEBUG_STDOUT);
8798
8799         load_case_tables();
8800
8801         if (is_default_dyn_CONFIGFILE()) {
8802                 if(getenv("SMB_CONF_PATH")) {
8803                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
8804                 }
8805         }
8806         lp_load(get_dyn_CONFIGFILE(),True,False,False,True);
8807         load_interfaces();
8808
8809         if (argc < 2) {
8810                 usage();
8811         }
8812
8813         for(p = argv[1]; *p; p++)
8814           if(*p == '\\')
8815             *p = '/';
8816
8817         if (strncmp(argv[1], "//", 2)) {
8818                 usage();
8819         }
8820
8821         fstrcpy(host, &argv[1][2]);
8822         p = strchr_m(&host[2],'/');
8823         if (!p) {
8824                 usage();
8825         }
8826         *p = 0;
8827         fstrcpy(share, p+1);
8828
8829         fstrcpy(myname, get_myname(talloc_tos()));
8830         if (!*myname) {
8831                 fprintf(stderr, "Failed to get my hostname.\n");
8832                 return 1;
8833         }
8834
8835         if (*username == 0 && getenv("LOGNAME")) {
8836           fstrcpy(username,getenv("LOGNAME"));
8837         }
8838
8839         argc--;
8840         argv++;
8841
8842         fstrcpy(workgroup, lp_workgroup());
8843
8844         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
8845                != EOF) {
8846                 switch (opt) {
8847                 case 'p':
8848                         port_to_use = atoi(optarg);
8849                         break;
8850                 case 's':
8851                         seed = atoi(optarg);
8852                         break;
8853                 case 'W':
8854                         fstrcpy(workgroup,optarg);
8855                         break;
8856                 case 'm':
8857                         max_protocol = interpret_protocol(optarg, max_protocol);
8858                         break;
8859                 case 'N':
8860                         nprocs = atoi(optarg);
8861                         break;
8862                 case 'o':
8863                         torture_numops = atoi(optarg);
8864                         break;
8865                 case 'd':
8866                         lp_set_cmdline("log level", optarg);
8867                         break;
8868                 case 'O':
8869                         sockops = optarg;
8870                         break;
8871                 case 'L':
8872                         use_oplocks = True;
8873                         break;
8874                 case 'l':
8875                         local_path = optarg;
8876                         break;
8877                 case 'A':
8878                         torture_showall = True;
8879                         break;
8880                 case 'n':
8881                         fstrcpy(myname, optarg);
8882                         break;
8883                 case 'c':
8884                         client_txt = optarg;
8885                         break;
8886                 case 'e':
8887                         do_encrypt = true;
8888                         break;
8889                 case 'k':
8890 #ifdef HAVE_KRB5
8891                         use_kerberos = True;
8892 #else
8893                         d_printf("No kerberos support compiled in\n");
8894                         exit(1);
8895 #endif
8896                         break;
8897                 case 'U':
8898                         gotuser = 1;
8899                         fstrcpy(username,optarg);
8900                         p = strchr_m(username,'%');
8901                         if (p) {
8902                                 *p = 0;
8903                                 fstrcpy(password, p+1);
8904                                 gotpass = 1;
8905                         }
8906                         break;
8907                 case 'b':
8908                         fstrcpy(multishare_conn_fname, optarg);
8909                         use_multishare_conn = True;
8910                         break;
8911                 case 'B':
8912                         torture_blocksize = atoi(optarg);
8913                         break;
8914                 case 'f':
8915                         test_filename = SMB_STRDUP(optarg);
8916                         break;
8917                 default:
8918                         printf("Unknown option %c (%d)\n", (char)opt, opt);
8919                         usage();
8920                 }
8921         }
8922
8923         d_printf("using seed %d\n", seed);
8924
8925         srandom(seed);
8926
8927         if(use_kerberos && !gotuser) gotpass = True;
8928
8929         while (!gotpass) {
8930                 p = getpass("Password:");
8931                 if (p) {
8932                         fstrcpy(password, p);
8933                         gotpass = 1;
8934                 }
8935         }
8936
8937         printf("host=%s share=%s user=%s myname=%s\n", 
8938                host, share, username, myname);
8939
8940         if (argc == optind) {
8941                 correct = run_test("ALL");
8942         } else {
8943                 for (i=optind;i<argc;i++) {
8944                         if (!run_test(argv[i])) {
8945                                 correct = False;
8946                         }
8947                 }
8948         }
8949
8950         TALLOC_FREE(frame);
8951
8952         if (correct) {
8953                 return(0);
8954         } else {
8955                 return(1);
8956         }
8957 }