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