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