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