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