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