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