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