torture3: local-messaging-read3
[mat/samba.git] / source3 / torture / torture.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-1998
5    Copyright (C) Jeremy Allison 2009
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/shmem.h"
23 #include "wbc_async.h"
24 #include "torture/proto.h"
25 #include "libcli/security/security.h"
26 #include "tldap.h"
27 #include "tldap_util.h"
28 #include "../librpc/gen_ndr/svcctl.h"
29 #include "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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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))) {
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);
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);
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, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4794           printf("Opening original file after rename of open file fails: %s\n",
4795               cli_errstr(cli1));
4796         }
4797         else {
4798           printf("Opening original file after rename of open file works ...\n");
4799           (void)cli_close(cli1, fnum2);
4800           } */
4801
4802         /*--*/
4803         status = cli_close(cli1, fnum1);
4804         if (!NT_STATUS_IS_OK(status)) {
4805                 printf("close - 5 failed (%s)\n", nt_errstr(status));
4806                 return False;
4807         }
4808
4809         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4810         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4811         if (!NT_STATUS_IS_OK(status)) {
4812                 printf("getatr on file %s failed - %s ! \n",
4813                         fname1, nt_errstr(status));
4814                 correct = False;
4815         } else {
4816                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4817                         printf("Renamed file %s has wrong attr 0x%x "
4818                                 "(should be 0x%x)\n",
4819                                 fname1,
4820                                 attr,
4821                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4822                         correct = False;
4823                 } else {
4824                         printf("Renamed file %s has archive bit set\n", fname1);
4825                 }
4826         }
4827
4828         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4829         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4830
4831         if (!torture_close_connection(cli1)) {
4832                 correct = False;
4833         }
4834
4835         return correct;
4836 }
4837
4838 static bool run_pipe_number(int dummy)
4839 {
4840         struct cli_state *cli1;
4841         const char *pipe_name = "\\SPOOLSS";
4842         uint16_t fnum;
4843         int num_pipes = 0;
4844         NTSTATUS status;
4845
4846         printf("starting pipenumber test\n");
4847         if (!torture_open_connection(&cli1, 0)) {
4848                 return False;
4849         }
4850
4851         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4852         while(1) {
4853                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
4854                                       FILE_ATTRIBUTE_NORMAL,
4855                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
4856                                       FILE_OPEN_IF, 0, 0, &fnum);
4857                 if (!NT_STATUS_IS_OK(status)) {
4858                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
4859                         break;
4860                 }
4861                 num_pipes++;
4862                 printf("\r%6d", num_pipes);
4863         }
4864
4865         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4866         torture_close_connection(cli1);
4867         return True;
4868 }
4869
4870 /*
4871   Test open mode returns on read-only files.
4872  */
4873 static bool run_opentest(int dummy)
4874 {
4875         static struct cli_state *cli1;
4876         static struct cli_state *cli2;
4877         const char *fname = "\\readonly.file";
4878         uint16_t fnum1, fnum2;
4879         char buf[20];
4880         off_t fsize;
4881         bool correct = True;
4882         char *tmp_path;
4883         NTSTATUS status;
4884
4885         printf("starting open test\n");
4886
4887         if (!torture_open_connection(&cli1, 0)) {
4888                 return False;
4889         }
4890
4891         cli_setatr(cli1, fname, 0, 0);
4892         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4893
4894         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4895
4896         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4897         if (!NT_STATUS_IS_OK(status)) {
4898                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4899                 return False;
4900         }
4901
4902         status = cli_close(cli1, fnum1);
4903         if (!NT_STATUS_IS_OK(status)) {
4904                 printf("close2 failed (%s)\n", nt_errstr(status));
4905                 return False;
4906         }
4907
4908         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
4909         if (!NT_STATUS_IS_OK(status)) {
4910                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
4911                 return False;
4912         }
4913
4914         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4915         if (!NT_STATUS_IS_OK(status)) {
4916                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4917                 return False;
4918         }
4919
4920         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4921         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4922
4923         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
4924                         NT_STATUS_ACCESS_DENIED)) {
4925                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4926         }
4927
4928         printf("finished open test 1\n");
4929
4930         cli_close(cli1, fnum1);
4931
4932         /* Now try not readonly and ensure ERRbadshare is returned. */
4933
4934         cli_setatr(cli1, fname, 0, 0);
4935
4936         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4937         if (!NT_STATUS_IS_OK(status)) {
4938                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4939                 return False;
4940         }
4941
4942         /* This will fail - but the error should be ERRshare. */
4943         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4944
4945         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
4946                         NT_STATUS_SHARING_VIOLATION)) {
4947                 printf("correct error code ERRDOS/ERRbadshare returned\n");
4948         }
4949
4950         status = cli_close(cli1, fnum1);
4951         if (!NT_STATUS_IS_OK(status)) {
4952                 printf("close2 failed (%s)\n", nt_errstr(status));
4953                 return False;
4954         }
4955
4956         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4957
4958         printf("finished open test 2\n");
4959
4960         /* Test truncate open disposition on file opened for read. */
4961         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4962         if (!NT_STATUS_IS_OK(status)) {
4963                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
4964                 return False;
4965         }
4966
4967         /* write 20 bytes. */
4968
4969         memset(buf, '\0', 20);
4970
4971         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
4972         if (!NT_STATUS_IS_OK(status)) {
4973                 printf("write failed (%s)\n", nt_errstr(status));
4974                 correct = False;
4975         }
4976
4977         status = cli_close(cli1, fnum1);
4978         if (!NT_STATUS_IS_OK(status)) {
4979                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
4980                 return False;
4981         }
4982
4983         /* Ensure size == 20. */
4984         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4985         if (!NT_STATUS_IS_OK(status)) {
4986                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4987                 return False;
4988         }
4989
4990         if (fsize != 20) {
4991                 printf("(3) file size != 20\n");
4992                 return False;
4993         }
4994
4995         /* Now test if we can truncate a file opened for readonly. */
4996         status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
4997         if (!NT_STATUS_IS_OK(status)) {
4998                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
4999                 return False;
5000         }
5001
5002         status = cli_close(cli1, fnum1);
5003         if (!NT_STATUS_IS_OK(status)) {
5004                 printf("close2 failed (%s)\n", nt_errstr(status));
5005                 return False;
5006         }
5007
5008         /* Ensure size == 0. */
5009         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5010         if (!NT_STATUS_IS_OK(status)) {
5011                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5012                 return False;
5013         }
5014
5015         if (fsize != 0) {
5016                 printf("(3) file size != 0\n");
5017                 return False;
5018         }
5019         printf("finished open test 3\n");
5020
5021         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5022
5023         printf("Do ctemp tests\n");
5024         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
5025         if (!NT_STATUS_IS_OK(status)) {
5026                 printf("ctemp failed (%s)\n", nt_errstr(status));
5027                 return False;
5028         }
5029
5030         printf("ctemp gave path %s\n", tmp_path);
5031         status = cli_close(cli1, fnum1);
5032         if (!NT_STATUS_IS_OK(status)) {
5033                 printf("close of temp failed (%s)\n", nt_errstr(status));
5034         }
5035
5036         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5037         if (!NT_STATUS_IS_OK(status)) {
5038                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
5039         }
5040
5041         /* Test the non-io opens... */
5042
5043         if (!torture_open_connection(&cli2, 1)) {
5044                 return False;
5045         }
5046
5047         cli_setatr(cli2, fname, 0, 0);
5048         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5049
5050         smbXcli_conn_set_sockopt(cli2->conn, sockops);
5051
5052         printf("TEST #1 testing 2 non-io opens (no delete)\n");
5053         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5054                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5055                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5056         if (!NT_STATUS_IS_OK(status)) {
5057                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5058                 return False;
5059         }
5060
5061         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5062                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5063                               FILE_OPEN_IF, 0, 0, &fnum2);
5064         if (!NT_STATUS_IS_OK(status)) {
5065                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5066                 return False;
5067         }
5068
5069         status = cli_close(cli1, fnum1);
5070         if (!NT_STATUS_IS_OK(status)) {
5071                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5072                 return False;
5073         }
5074
5075         status = cli_close(cli2, fnum2);
5076         if (!NT_STATUS_IS_OK(status)) {
5077                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5078                 return False;
5079         }
5080
5081         printf("non-io open test #1 passed.\n");
5082
5083         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5084
5085         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5086
5087         status = cli_ntcreate(cli1, fname, 0,
5088                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5089                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5090                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5091         if (!NT_STATUS_IS_OK(status)) {
5092                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5093                 return False;
5094         }
5095
5096         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5097                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5098                               FILE_OPEN_IF, 0, 0, &fnum2);
5099         if (!NT_STATUS_IS_OK(status)) {
5100                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5101                 return False;
5102         }
5103
5104         status = cli_close(cli1, fnum1);
5105         if (!NT_STATUS_IS_OK(status)) {
5106                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5107                 return False;
5108         }
5109
5110         status = cli_close(cli2, fnum2);
5111         if (!NT_STATUS_IS_OK(status)) {
5112                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5113                 return False;
5114         }
5115
5116         printf("non-io open test #2 passed.\n");
5117
5118         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5119
5120         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5121
5122         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5123                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5124                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5125         if (!NT_STATUS_IS_OK(status)) {
5126                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5127                 return False;
5128         }
5129
5130         status = cli_ntcreate(cli2, fname, 0,
5131                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5132                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5133                               FILE_OPEN_IF, 0, 0, &fnum2);
5134         if (!NT_STATUS_IS_OK(status)) {
5135                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5136                 return False;
5137         }
5138
5139         status = cli_close(cli1, fnum1);
5140         if (!NT_STATUS_IS_OK(status)) {
5141                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5142                 return False;
5143         }
5144
5145         status = cli_close(cli2, fnum2);
5146         if (!NT_STATUS_IS_OK(status)) {
5147                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5148                 return False;
5149         }
5150
5151         printf("non-io open test #3 passed.\n");
5152
5153         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5154
5155         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5156
5157         status = cli_ntcreate(cli1, fname, 0,
5158                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5159                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5160                                FILE_OVERWRITE_IF, 0, 0, &fnum1);
5161         if (!NT_STATUS_IS_OK(status)) {
5162                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5163                 return False;
5164         }
5165
5166         status = cli_ntcreate(cli2, fname, 0,
5167                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5168                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5169                               FILE_OPEN_IF, 0, 0, &fnum2);
5170         if (NT_STATUS_IS_OK(status)) {
5171                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5172                 return False;
5173         }
5174
5175         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5176
5177         status = cli_close(cli1, fnum1);
5178         if (!NT_STATUS_IS_OK(status)) {
5179                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5180                 return False;
5181         }
5182
5183         printf("non-io open test #4 passed.\n");
5184
5185         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5186
5187         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5188
5189         status = cli_ntcreate(cli1, fname, 0,
5190                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5191                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5192                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5193         if (!NT_STATUS_IS_OK(status)) {
5194                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5195                 return False;
5196         }
5197
5198         status = cli_ntcreate(cli2, fname, 0,
5199                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5200                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5201                               FILE_OPEN_IF, 0, 0, &fnum2);
5202         if (!NT_STATUS_IS_OK(status)) {
5203                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5204                 return False;
5205         }
5206
5207         status = cli_close(cli1, fnum1);
5208         if (!NT_STATUS_IS_OK(status)) {
5209                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5210                 return False;
5211         }
5212
5213         status = cli_close(cli2, fnum2);
5214         if (!NT_STATUS_IS_OK(status)) {
5215                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5216                 return False;
5217         }
5218
5219         printf("non-io open test #5 passed.\n");
5220
5221         printf("TEST #6 testing 1 non-io open, one io open\n");
5222
5223         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5224
5225         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5226                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5227                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5228         if (!NT_STATUS_IS_OK(status)) {
5229                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5230                 return False;
5231         }
5232
5233         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5234                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5235                               FILE_OPEN_IF, 0, 0, &fnum2);
5236         if (!NT_STATUS_IS_OK(status)) {
5237                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5238                 return False;
5239         }
5240
5241         status = cli_close(cli1, fnum1);
5242         if (!NT_STATUS_IS_OK(status)) {
5243                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5244                 return False;
5245         }
5246
5247         status = cli_close(cli2, fnum2);
5248         if (!NT_STATUS_IS_OK(status)) {
5249                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5250                 return False;
5251         }
5252
5253         printf("non-io open test #6 passed.\n");
5254
5255         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5256
5257         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5258
5259         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5260                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5261                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5262         if (!NT_STATUS_IS_OK(status)) {
5263                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5264                 return False;
5265         }
5266
5267         status = cli_ntcreate(cli2, fname, 0,
5268                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5269                               FILE_ATTRIBUTE_NORMAL,
5270                               FILE_SHARE_READ|FILE_SHARE_DELETE,
5271                               FILE_OPEN_IF, 0, 0, &fnum2);
5272         if (NT_STATUS_IS_OK(status)) {
5273                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5274                 return False;
5275         }
5276
5277         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5278
5279         status = cli_close(cli1, fnum1);
5280         if (!NT_STATUS_IS_OK(status)) {
5281                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5282                 return False;
5283         }
5284
5285         printf("non-io open test #7 passed.\n");
5286
5287         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5288
5289         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5290         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5291                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5292                                 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5293         if (!NT_STATUS_IS_OK(status)) {
5294                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5295                 correct = false;
5296                 goto out;
5297         }
5298
5299         /* Write to ensure we have to update the file time. */
5300         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5301                               NULL);
5302         if (!NT_STATUS_IS_OK(status)) {
5303                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5304                 correct = false;
5305                 goto out;
5306         }
5307
5308         status = cli_close(cli1, fnum1);
5309         if (!NT_STATUS_IS_OK(status)) {
5310                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5311                 correct = false;
5312         }
5313
5314   out:
5315
5316         if (!torture_close_connection(cli1)) {
5317                 correct = False;
5318         }
5319         if (!torture_close_connection(cli2)) {
5320                 correct = False;
5321         }
5322
5323         return correct;
5324 }
5325
5326 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5327 {
5328         uint16 major, minor;
5329         uint32 caplow, caphigh;
5330         NTSTATUS status;
5331
5332         if (!SERVER_HAS_UNIX_CIFS(cli)) {
5333                 printf("Server doesn't support UNIX CIFS extensions.\n");
5334                 return NT_STATUS_NOT_SUPPORTED;
5335         }
5336
5337         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5338                                              &caphigh);
5339         if (!NT_STATUS_IS_OK(status)) {
5340                 printf("Server didn't return UNIX CIFS extensions: %s\n",
5341                        nt_errstr(status));
5342                 return status;
5343         }
5344
5345         status = cli_set_unix_extensions_capabilities(cli, major, minor,
5346                                                       caplow, caphigh);
5347         if (!NT_STATUS_IS_OK(status)) {
5348                 printf("Server doesn't support setting UNIX CIFS extensions: "
5349                        "%s.\n", nt_errstr(status));
5350                 return status;
5351         }
5352
5353         return NT_STATUS_OK;
5354 }
5355
5356 /*
5357   Test POSIX open /mkdir calls.
5358  */
5359 static bool run_simple_posix_open_test(int dummy)
5360 {
5361         static struct cli_state *cli1;
5362         const char *fname = "posix:file";
5363         const char *hname = "posix:hlink";
5364         const char *sname = "posix:symlink";
5365         const char *dname = "posix:dir";
5366         char buf[10];
5367         char namebuf[11];
5368         uint16_t fnum1 = (uint16_t)-1;
5369         SMB_STRUCT_STAT sbuf;
5370         bool correct = false;
5371         NTSTATUS status;
5372         size_t nread;
5373         const char *fname_windows = "windows_file";
5374         uint16_t fnum2 = (uint16_t)-1;
5375
5376         printf("Starting simple POSIX open test\n");
5377
5378         if (!torture_open_connection(&cli1, 0)) {
5379                 return false;
5380         }
5381
5382         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5383
5384         status = torture_setup_unix_extensions(cli1);
5385         if (!NT_STATUS_IS_OK(status)) {
5386                 return false;
5387         }
5388
5389         cli_setatr(cli1, fname, 0, 0);
5390         cli_posix_unlink(cli1, fname);
5391         cli_setatr(cli1, dname, 0, 0);
5392         cli_posix_rmdir(cli1, dname);
5393         cli_setatr(cli1, hname, 0, 0);
5394         cli_posix_unlink(cli1, hname);
5395         cli_setatr(cli1, sname, 0, 0);
5396         cli_posix_unlink(cli1, sname);
5397         cli_setatr(cli1, fname_windows, 0, 0);
5398         cli_posix_unlink(cli1, fname_windows);
5399
5400         /* Create a directory. */
5401         status = cli_posix_mkdir(cli1, dname, 0777);
5402         if (!NT_STATUS_IS_OK(status)) {
5403                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5404                 goto out;
5405         }
5406
5407         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5408                                 0600, &fnum1);
5409         if (!NT_STATUS_IS_OK(status)) {
5410                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5411                 goto out;
5412         }
5413
5414         /* Test ftruncate - set file size. */
5415         status = cli_ftruncate(cli1, fnum1, 1000);
5416         if (!NT_STATUS_IS_OK(status)) {
5417                 printf("ftruncate failed (%s)\n", nt_errstr(status));
5418                 goto out;
5419         }
5420
5421         /* Ensure st_size == 1000 */
5422         status = cli_posix_stat(cli1, fname, &sbuf);
5423         if (!NT_STATUS_IS_OK(status)) {
5424                 printf("stat failed (%s)\n", nt_errstr(status));
5425                 goto out;
5426         }
5427
5428         if (sbuf.st_ex_size != 1000) {
5429                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5430                 goto out;
5431         }
5432
5433         /* Ensure st_mode == 0600 */
5434         if ((sbuf.st_ex_mode & 07777) != 0600) {
5435                 printf("posix_open - bad permissions 0%o != 0600\n",
5436                                 (unsigned int)(sbuf.st_ex_mode & 07777));
5437                 goto out;
5438         }
5439
5440         /* Test ftruncate - set file size back to zero. */
5441         status = cli_ftruncate(cli1, fnum1, 0);
5442         if (!NT_STATUS_IS_OK(status)) {
5443                 printf("ftruncate failed (%s)\n", nt_errstr(status));
5444                 goto out;
5445         }
5446
5447         status = cli_close(cli1, fnum1);
5448         if (!NT_STATUS_IS_OK(status)) {
5449                 printf("close failed (%s)\n", nt_errstr(status));
5450                 goto out;
5451         }
5452
5453         /* Now open the file again for read only. */
5454         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5455         if (!NT_STATUS_IS_OK(status)) {
5456                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5457                 goto out;
5458         }
5459
5460         /* Now unlink while open. */
5461         status = cli_posix_unlink(cli1, fname);
5462         if (!NT_STATUS_IS_OK(status)) {
5463                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5464                 goto out;
5465         }
5466
5467         status = cli_close(cli1, fnum1);
5468         if (!NT_STATUS_IS_OK(status)) {
5469                 printf("close(2) failed (%s)\n", nt_errstr(status));
5470                 goto out;
5471         }
5472
5473         /* Ensure the file has gone. */
5474         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5475         if (NT_STATUS_IS_OK(status)) {
5476                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5477                 goto out;
5478         }
5479
5480         /* Create again to test open with O_TRUNC. */
5481         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
5482         if (!NT_STATUS_IS_OK(status)) {
5483                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5484                 goto out;
5485         }
5486
5487         /* Test ftruncate - set file size. */
5488         status = cli_ftruncate(cli1, fnum1, 1000);
5489         if (!NT_STATUS_IS_OK(status)) {
5490                 printf("ftruncate failed (%s)\n", nt_errstr(status));
5491                 goto out;
5492         }
5493
5494         /* Ensure st_size == 1000 */
5495         status = cli_posix_stat(cli1, fname, &sbuf);
5496         if (!NT_STATUS_IS_OK(status)) {
5497                 printf("stat failed (%s)\n", nt_errstr(status));
5498                 goto out;
5499         }
5500
5501         if (sbuf.st_ex_size != 1000) {
5502                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5503                 goto out;
5504         }
5505
5506         status = cli_close(cli1, fnum1);
5507         if (!NT_STATUS_IS_OK(status)) {
5508                 printf("close(2) failed (%s)\n", nt_errstr(status));
5509                 goto out;
5510         }
5511
5512         /* Re-open with O_TRUNC. */
5513         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
5514         if (!NT_STATUS_IS_OK(status)) {
5515                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5516                 goto out;
5517         }
5518
5519         /* Ensure st_size == 0 */
5520         status = cli_posix_stat(cli1, fname, &sbuf);
5521         if (!NT_STATUS_IS_OK(status)) {
5522                 printf("stat failed (%s)\n", nt_errstr(status));
5523                 goto out;
5524         }
5525
5526         if (sbuf.st_ex_size != 0) {
5527                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5528                 goto out;
5529         }
5530
5531         status = cli_close(cli1, fnum1);
5532         if (!NT_STATUS_IS_OK(status)) {
5533                 printf("close failed (%s)\n", nt_errstr(status));
5534                 goto out;
5535         }
5536
5537         status = cli_posix_unlink(cli1, fname);
5538         if (!NT_STATUS_IS_OK(status)) {
5539                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5540                 goto out;
5541         }
5542
5543         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
5544         if (!NT_STATUS_IS_OK(status)) {
5545                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5546                         dname, nt_errstr(status));
5547                 goto out;
5548         }
5549
5550         cli_close(cli1, fnum1);
5551
5552         /* What happens when we try and POSIX open a directory for write ? */
5553         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
5554         if (NT_STATUS_IS_OK(status)) {
5555                 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5556                 goto out;
5557         } else {
5558                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
5559                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5560                         goto out;
5561                 }
5562         }
5563
5564         /* Create the file. */
5565         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5566                                 0600, &fnum1);
5567         if (!NT_STATUS_IS_OK(status)) {
5568                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5569                 goto out;
5570         }
5571
5572         /* Write some data into it. */
5573         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5574                               NULL);
5575         if (!NT_STATUS_IS_OK(status)) {
5576                 printf("cli_write failed: %s\n", nt_errstr(status));
5577                 goto out;
5578         }
5579
5580         cli_close(cli1, fnum1);
5581
5582         /* Now create a hardlink. */
5583         status = cli_posix_hardlink(cli1, fname, hname);
5584         if (!NT_STATUS_IS_OK(status)) {
5585                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5586                 goto out;
5587         }
5588
5589         /* Now create a symlink. */
5590         status = cli_posix_symlink(cli1, fname, sname);
5591         if (!NT_STATUS_IS_OK(status)) {
5592                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5593                 goto out;
5594         }
5595
5596         /* Open the hardlink for read. */
5597         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5598         if (!NT_STATUS_IS_OK(status)) {
5599                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5600                 goto out;
5601         }
5602
5603         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
5604         if (!NT_STATUS_IS_OK(status)) {
5605                 printf("POSIX read of %s failed (%s)\n", hname,
5606                        nt_errstr(status));
5607                 goto out;
5608         } else if (nread != 10) {
5609                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
5610                        hname, (unsigned long)nread, 10);
5611                 goto out;
5612         }
5613
5614         if (memcmp(buf, "TEST DATA\n", 10)) {
5615                 printf("invalid data read from hardlink\n");
5616                 goto out;
5617         }
5618
5619         /* Do a POSIX lock/unlock. */
5620         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5621         if (!NT_STATUS_IS_OK(status)) {
5622                 printf("POSIX lock failed %s\n", nt_errstr(status));
5623                 goto out;
5624         }
5625
5626         /* Punch a hole in the locked area. */
5627         status = cli_posix_unlock(cli1, fnum1, 10, 80);
5628         if (!NT_STATUS_IS_OK(status)) {
5629                 printf("POSIX unlock failed %s\n", nt_errstr(status));
5630                 goto out;
5631         }
5632
5633         cli_close(cli1, fnum1);
5634
5635         /* Open the symlink for read - this should fail. A POSIX
5636            client should not be doing opens on a symlink. */
5637         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5638         if (NT_STATUS_IS_OK(status)) {
5639                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5640                 goto out;
5641         } else {
5642                 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
5643                                 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5644                         printf("POSIX open of %s should have failed "
5645                                 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5646                                 "failed with %s instead.\n",
5647                                 sname, nt_errstr(status));
5648                         goto out;
5649                 }
5650         }
5651
5652         status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5653         if (!NT_STATUS_IS_OK(status)) {
5654                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5655                 goto out;
5656         }
5657
5658         if (strcmp(namebuf, fname) != 0) {
5659                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5660                         sname, fname, namebuf);
5661                 goto out;
5662         }
5663
5664         status = cli_posix_rmdir(cli1, dname);
5665         if (!NT_STATUS_IS_OK(status)) {
5666                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5667                 goto out;
5668         }
5669
5670         /* Check directory opens with a specific permission. */
5671         status = cli_posix_mkdir(cli1, dname, 0700);
5672         if (!NT_STATUS_IS_OK(status)) {
5673                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5674                 goto out;
5675         }
5676
5677         /* Ensure st_mode == 0700 */
5678         status = cli_posix_stat(cli1, dname, &sbuf);
5679         if (!NT_STATUS_IS_OK(status)) {
5680                 printf("stat failed (%s)\n", nt_errstr(status));
5681                 goto out;
5682         }
5683
5684         if ((sbuf.st_ex_mode & 07777) != 0700) {
5685                 printf("posix_mkdir - bad permissions 0%o != 0700\n",
5686                                 (unsigned int)(sbuf.st_ex_mode & 07777));
5687                 goto out;
5688         }
5689
5690         /*
5691          * Now create a Windows file, and attempt a POSIX unlink.
5692          * This should fail with a sharing violation but due to:
5693          *
5694          * [Bug 9571] Unlink after open causes smbd to panic
5695          *
5696          * ensure we've fixed the lock ordering violation.
5697          */
5698
5699         status = cli_ntcreate(cli1, fname_windows, 0,
5700                         FILE_READ_DATA|FILE_WRITE_DATA, 0,
5701                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5702                         FILE_CREATE,
5703                         0x0, 0x0, &fnum2);
5704         if (!NT_STATUS_IS_OK(status)) {
5705                 printf("Windows create of %s failed (%s)\n", fname_windows,
5706                         nt_errstr(status));
5707                 goto out;
5708         }
5709
5710         /* Now try posix_unlink. */
5711         status = cli_posix_unlink(cli1, fname_windows);
5712         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5713                 printf("POSIX unlink of %s should fail "
5714                         "with NT_STATUS_SHARING_VIOLATION "
5715                         "got %s instead !\n",
5716                         fname_windows,
5717                         nt_errstr(status));
5718                 goto out;
5719         }
5720
5721         cli_close(cli1, fnum2);
5722
5723         printf("Simple POSIX open test passed\n");
5724         correct = true;
5725
5726   out:
5727
5728         if (fnum1 != (uint16_t)-1) {
5729                 cli_close(cli1, fnum1);
5730                 fnum1 = (uint16_t)-1;
5731         }
5732
5733         if (fnum2 != (uint16_t)-1) {
5734                 cli_close(cli1, fnum2);
5735                 fnum2 = (uint16_t)-1;
5736         }
5737
5738         cli_setatr(cli1, sname, 0, 0);
5739         cli_posix_unlink(cli1, sname);
5740         cli_setatr(cli1, hname, 0, 0);
5741         cli_posix_unlink(cli1, hname);
5742         cli_setatr(cli1, fname, 0, 0);
5743         cli_posix_unlink(cli1, fname);
5744         cli_setatr(cli1, dname, 0, 0);
5745         cli_posix_rmdir(cli1, dname);
5746         cli_setatr(cli1, fname_windows, 0, 0);
5747         cli_posix_unlink(cli1, fname_windows);
5748
5749         if (!torture_close_connection(cli1)) {
5750                 correct = false;
5751         }
5752
5753         return correct;
5754 }
5755
5756
5757 static uint32 open_attrs_table[] = {
5758                 FILE_ATTRIBUTE_NORMAL,
5759                 FILE_ATTRIBUTE_ARCHIVE,
5760                 FILE_ATTRIBUTE_READONLY,
5761                 FILE_ATTRIBUTE_HIDDEN,
5762                 FILE_ATTRIBUTE_SYSTEM,
5763
5764                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
5765                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
5766                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
5767                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5768                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5769                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5770
5771                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5772                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5773                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5774                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
5775 };
5776
5777 struct trunc_open_results {
5778         unsigned int num;
5779         uint32 init_attr;
5780         uint32 trunc_attr;
5781         uint32 result_attr;
5782 };
5783
5784 static struct trunc_open_results attr_results[] = {
5785         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5786         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5787         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5788         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5789         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5790         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5791         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5792         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5793         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5794         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5795         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5796         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5797         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5798         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5799         { 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 },
5800         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5801         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5802         { 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 },
5803         { 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 },
5804         { 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 },
5805         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5806         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5807         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5808         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5809         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5810         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
5811 };
5812
5813 static bool run_openattrtest(int dummy)
5814 {
5815         static struct cli_state *cli1;
5816         const char *fname = "\\openattr.file";
5817         uint16_t fnum1;
5818         bool correct = True;
5819         uint16 attr;
5820         unsigned int i, j, k, l;
5821         NTSTATUS status;
5822
5823         printf("starting open attr test\n");
5824
5825         if (!torture_open_connection(&cli1, 0)) {
5826                 return False;
5827         }
5828
5829         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5830
5831         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
5832                 cli_setatr(cli1, fname, 0, 0);
5833                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5834
5835                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
5836                                        open_attrs_table[i], FILE_SHARE_NONE,
5837                                        FILE_OVERWRITE_IF, 0, 0, &fnum1);
5838                 if (!NT_STATUS_IS_OK(status)) {
5839                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5840                         return False;
5841                 }
5842
5843                 status = cli_close(cli1, fnum1);
5844                 if (!NT_STATUS_IS_OK(status)) {
5845                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5846                         return False;
5847                 }
5848
5849                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
5850                         status = cli_ntcreate(cli1, fname, 0,
5851                                               FILE_READ_DATA|FILE_WRITE_DATA,
5852                                               open_attrs_table[j],
5853                                               FILE_SHARE_NONE, FILE_OVERWRITE,
5854                                               0, 0, &fnum1);
5855                         if (!NT_STATUS_IS_OK(status)) {
5856                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5857                                         if (attr_results[l].num == k) {
5858                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
5859                                                                 k, open_attrs_table[i],
5860                                                                 open_attrs_table[j],
5861                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
5862                                                 correct = False;
5863                                         }
5864                                 }
5865
5866                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5867                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
5868                                                         k, open_attrs_table[i], open_attrs_table[j],
5869                                                         nt_errstr(status));
5870                                         correct = False;
5871                                 }
5872 #if 0
5873                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
5874 #endif
5875                                 k++;
5876                                 continue;
5877                         }
5878
5879                         status = cli_close(cli1, fnum1);
5880                         if (!NT_STATUS_IS_OK(status)) {
5881                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
5882                                 return False;
5883                         }
5884
5885                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
5886                         if (!NT_STATUS_IS_OK(status)) {
5887                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
5888                                 return False;
5889                         }
5890
5891 #if 0
5892                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
5893                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
5894 #endif
5895
5896                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5897                                 if (attr_results[l].num == k) {
5898                                         if (attr != attr_results[l].result_attr ||
5899                                                         open_attrs_table[i] != attr_results[l].init_attr ||
5900                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
5901                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
5902                                                 open_attrs_table[i],
5903                                                 open_attrs_table[j],
5904                                                 (unsigned int)attr,
5905                                                 attr_results[l].result_attr);
5906                                                 correct = False;
5907                                         }
5908                                         break;
5909                                 }
5910                         }
5911                         k++;
5912                 }
5913         }
5914
5915         cli_setatr(cli1, fname, 0, 0);
5916         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5917
5918         printf("open attr test %s.\n", correct ? "passed" : "failed");
5919
5920         if (!torture_close_connection(cli1)) {
5921                 correct = False;
5922         }
5923         return correct;
5924 }
5925
5926 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
5927                     const char *name, void *state)
5928 {
5929         int *matched = (int *)state;
5930         if (matched != NULL) {
5931                 *matched += 1;
5932         }
5933         return NT_STATUS_OK;
5934 }
5935
5936 /*
5937   test directory listing speed
5938  */
5939 static bool run_dirtest(int dummy)
5940 {
5941         int i;
5942         static struct cli_state *cli;
5943         uint16_t fnum;
5944         struct timeval core_start;
5945         bool correct = True;
5946         int matched;
5947
5948         printf("starting directory test\n");
5949
5950         if (!torture_open_connection(&cli, 0)) {
5951                 return False;
5952         }
5953
5954         smbXcli_conn_set_sockopt(cli->conn, sockops);
5955
5956         srandom(0);
5957         for (i=0;i<torture_numops;i++) {
5958                 fstring fname;
5959                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5960                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
5961                         fprintf(stderr,"Failed to open %s\n", fname);
5962                         return False;
5963                 }
5964                 cli_close(cli, fnum);
5965         }
5966
5967         core_start = timeval_current();
5968
5969         matched = 0;
5970         cli_list(cli, "a*.*", 0, list_fn, &matched);
5971         printf("Matched %d\n", matched);
5972
5973         matched = 0;
5974         cli_list(cli, "b*.*", 0, list_fn, &matched);
5975         printf("Matched %d\n", matched);
5976
5977         matched = 0;
5978         cli_list(cli, "xyzabc", 0, list_fn, &matched);
5979         printf("Matched %d\n", matched);
5980
5981         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
5982
5983         srandom(0);
5984         for (i=0;i<torture_numops;i++) {
5985                 fstring fname;
5986                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5987                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5988         }
5989
5990         if (!torture_close_connection(cli)) {
5991                 correct = False;
5992         }
5993
5994         printf("finished dirtest\n");
5995
5996         return correct;
5997 }
5998
5999 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
6000                    void *state)
6001 {
6002         struct cli_state *pcli = (struct cli_state *)state;
6003         fstring fname;
6004         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
6005
6006         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
6007                 return NT_STATUS_OK;
6008
6009         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
6010                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
6011                         printf("del_fn: failed to rmdir %s\n,", fname );
6012         } else {
6013                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
6014                         printf("del_fn: failed to unlink %s\n,", fname );
6015         }
6016         return NT_STATUS_OK;
6017 }
6018
6019
6020 /*
6021   sees what IOCTLs are supported
6022  */
6023 bool torture_ioctl_test(int dummy)
6024 {
6025         static struct cli_state *cli;
6026         uint16_t device, function;
6027         uint16_t fnum;
6028         const char *fname = "\\ioctl.dat";
6029         DATA_BLOB blob;
6030         NTSTATUS status;
6031
6032         if (!torture_open_connection(&cli, 0)) {
6033                 return False;
6034         }
6035
6036         printf("starting ioctl test\n");
6037
6038         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6039
6040         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6041         if (!NT_STATUS_IS_OK(status)) {
6042                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6043                 return False;
6044         }
6045
6046         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
6047         printf("ioctl device info: %s\n", nt_errstr(status));
6048
6049         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
6050         printf("ioctl job info: %s\n", nt_errstr(status));
6051
6052         for (device=0;device<0x100;device++) {
6053                 printf("ioctl test with device = 0x%x\n", device);
6054                 for (function=0;function<0x100;function++) {
6055                         uint32 code = (device<<16) | function;
6056
6057                         status = cli_raw_ioctl(cli, fnum, code, &blob);
6058
6059                         if (NT_STATUS_IS_OK(status)) {
6060                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
6061                                        (int)blob.length);
6062                                 data_blob_free(&blob);
6063                         }
6064                 }
6065         }
6066
6067         if (!torture_close_connection(cli)) {
6068                 return False;
6069         }
6070
6071         return True;
6072 }
6073
6074
6075 /*
6076   tries varients of chkpath
6077  */
6078 bool torture_chkpath_test(int dummy)
6079 {
6080         static struct cli_state *cli;
6081         uint16_t fnum;
6082         bool ret;
6083         NTSTATUS status;
6084
6085         if (!torture_open_connection(&cli, 0)) {
6086                 return False;
6087         }
6088
6089         printf("starting chkpath test\n");
6090
6091         /* cleanup from an old run */
6092         cli_rmdir(cli, "\\chkpath.dir\\dir2");
6093         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6094         cli_rmdir(cli, "\\chkpath.dir");
6095
6096         status = cli_mkdir(cli, "\\chkpath.dir");
6097         if (!NT_STATUS_IS_OK(status)) {
6098                 printf("mkdir1 failed : %s\n", nt_errstr(status));
6099                 return False;
6100         }
6101
6102         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
6103         if (!NT_STATUS_IS_OK(status)) {
6104                 printf("mkdir2 failed : %s\n", nt_errstr(status));
6105                 return False;
6106         }
6107
6108         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
6109                           DENY_NONE, &fnum);
6110         if (!NT_STATUS_IS_OK(status)) {
6111                 printf("open1 failed (%s)\n", nt_errstr(status));
6112                 return False;
6113         }
6114         cli_close(cli, fnum);
6115
6116         status = cli_chkpath(cli, "\\chkpath.dir");
6117         if (!NT_STATUS_IS_OK(status)) {
6118                 printf("chkpath1 failed: %s\n", nt_errstr(status));
6119                 ret = False;
6120         }
6121
6122         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
6123         if (!NT_STATUS_IS_OK(status)) {
6124                 printf("chkpath2 failed: %s\n", nt_errstr(status));
6125                 ret = False;
6126         }
6127
6128         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
6129         if (!NT_STATUS_IS_OK(status)) {
6130                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6131                                   NT_STATUS_NOT_A_DIRECTORY);
6132         } else {
6133                 printf("* chkpath on a file should fail\n");
6134                 ret = False;
6135         }
6136
6137         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
6138         if (!NT_STATUS_IS_OK(status)) {
6139                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
6140                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
6141         } else {
6142                 printf("* chkpath on a non existent file should fail\n");
6143                 ret = False;
6144         }
6145
6146         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
6147         if (!NT_STATUS_IS_OK(status)) {
6148                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6149                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
6150         } else {
6151                 printf("* chkpath on a non existent component should fail\n");
6152                 ret = False;
6153         }
6154
6155         cli_rmdir(cli, "\\chkpath.dir\\dir2");
6156         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6157         cli_rmdir(cli, "\\chkpath.dir");
6158
6159         if (!torture_close_connection(cli)) {
6160                 return False;
6161         }
6162
6163         return ret;
6164 }
6165
6166 static bool run_eatest(int dummy)
6167 {
6168         static struct cli_state *cli;
6169         const char *fname = "\\eatest.txt";
6170         bool correct = True;
6171         uint16_t fnum;
6172         int i;
6173         size_t num_eas;
6174         struct ea_struct *ea_list = NULL;
6175         TALLOC_CTX *mem_ctx = talloc_init("eatest");
6176         NTSTATUS status;
6177
6178         printf("starting eatest\n");
6179
6180         if (!torture_open_connection(&cli, 0)) {
6181                 talloc_destroy(mem_ctx);
6182                 return False;
6183         }
6184
6185         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6186
6187         status = cli_ntcreate(cli, fname, 0,
6188                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6189                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
6190                               0x4044, 0, &fnum);
6191         if (!NT_STATUS_IS_OK(status)) {
6192                 printf("open failed - %s\n", nt_errstr(status));
6193                 talloc_destroy(mem_ctx);
6194                 return False;
6195         }
6196
6197         for (i = 0; i < 10; i++) {
6198                 fstring ea_name, ea_val;
6199
6200                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
6201                 memset(ea_val, (char)i+1, i+1);
6202                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
6203                 if (!NT_STATUS_IS_OK(status)) {
6204                         printf("ea_set of name %s failed - %s\n", ea_name,
6205                                nt_errstr(status));
6206                         talloc_destroy(mem_ctx);
6207                         return False;
6208                 }
6209         }
6210
6211         cli_close(cli, fnum);
6212         for (i = 0; i < 10; i++) {
6213                 fstring ea_name, ea_val;
6214
6215                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
6216                 memset(ea_val, (char)i+1, i+1);
6217                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
6218                 if (!NT_STATUS_IS_OK(status)) {
6219                         printf("ea_set of name %s failed - %s\n", ea_name,
6220                                nt_errstr(status));
6221                         talloc_destroy(mem_ctx);
6222                         return False;
6223                 }
6224         }
6225
6226         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6227         if (!NT_STATUS_IS_OK(status)) {
6228                 printf("ea_get list failed - %s\n", nt_errstr(status));
6229                 correct = False;
6230         }
6231
6232         printf("num_eas = %d\n", (int)num_eas);
6233
6234         if (num_eas != 20) {
6235                 printf("Should be 20 EA's stored... failing.\n");
6236                 correct = False;
6237         }
6238
6239         for (i = 0; i < num_eas; i++) {
6240                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6241                 dump_data(0, ea_list[i].value.data,
6242                           ea_list[i].value.length);
6243         }
6244
6245         /* Setting EA's to zero length deletes them. Test this */
6246         printf("Now deleting all EA's - case indepenent....\n");
6247
6248 #if 1
6249         cli_set_ea_path(cli, fname, "", "", 0);
6250 #else
6251         for (i = 0; i < 20; i++) {
6252                 fstring ea_name;
6253                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
6254                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
6255                 if (!NT_STATUS_IS_OK(status)) {
6256                         printf("ea_set of name %s failed - %s\n", ea_name,
6257                                nt_errstr(status));
6258                         talloc_destroy(mem_ctx);
6259                         return False;
6260                 }
6261         }
6262 #endif
6263
6264         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6265         if (!NT_STATUS_IS_OK(status)) {
6266                 printf("ea_get list failed - %s\n", nt_errstr(status));
6267                 correct = False;
6268         }
6269
6270         printf("num_eas = %d\n", (int)num_eas);
6271         for (i = 0; i < num_eas; i++) {
6272                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6273                 dump_data(0, ea_list[i].value.data,
6274                           ea_list[i].value.length);
6275         }
6276
6277         if (num_eas != 0) {
6278                 printf("deleting EA's failed.\n");
6279                 correct = False;
6280         }
6281
6282         /* Try and delete a non existent EA. */
6283         status = cli_set_ea_path(cli, fname, "foo", "", 0);
6284         if (!NT_STATUS_IS_OK(status)) {
6285                 printf("deleting non-existent EA 'foo' should succeed. %s\n",
6286                        nt_errstr(status));
6287                 correct = False;
6288         }
6289
6290         talloc_destroy(mem_ctx);
6291         if (!torture_close_connection(cli)) {
6292                 correct = False;
6293         }
6294
6295         return correct;
6296 }
6297
6298 static bool run_dirtest1(int dummy)
6299 {
6300         int i;
6301         static struct cli_state *cli;
6302         uint16_t fnum;
6303         int num_seen;
6304         bool correct = True;
6305
6306         printf("starting directory test\n");
6307
6308         if (!torture_open_connection(&cli, 0)) {
6309                 return False;
6310         }
6311
6312         smbXcli_conn_set_sockopt(cli->conn, sockops);
6313
6314         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6315         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6316         cli_rmdir(cli, "\\LISTDIR");
6317         cli_mkdir(cli, "\\LISTDIR");
6318
6319         /* Create 1000 files and 1000 directories. */
6320         for (i=0;i<1000;i++) {
6321                 fstring fname;
6322                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
6323                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6324                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6325                         fprintf(stderr,"Failed to open %s\n", fname);
6326                         return False;
6327                 }
6328                 cli_close(cli, fnum);
6329         }
6330         for (i=0;i<1000;i++) {
6331                 fstring fname;
6332                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
6333                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
6334                         fprintf(stderr,"Failed to open %s\n", fname);
6335                         return False;
6336                 }
6337         }
6338
6339         /* Now ensure that doing an old list sees both files and directories. */
6340         num_seen = 0;
6341         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6342         printf("num_seen = %d\n", num_seen );
6343         /* We should see 100 files + 1000 directories + . and .. */
6344         if (num_seen != 2002)
6345                 correct = False;
6346
6347         /* Ensure if we have the "must have" bits we only see the
6348          * relevent entries.
6349          */
6350         num_seen = 0;
6351         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6352         printf("num_seen = %d\n", num_seen );
6353         if (num_seen != 1002)
6354                 correct = False;
6355
6356         num_seen = 0;
6357         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6358         printf("num_seen = %d\n", num_seen );
6359         if (num_seen != 1000)
6360                 correct = False;
6361
6362         /* Delete everything. */
6363         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6364         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6365         cli_rmdir(cli, "\\LISTDIR");
6366
6367 #if 0
6368         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
6369         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
6370         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
6371 #endif
6372
6373         if (!torture_close_connection(cli)) {
6374                 correct = False;
6375         }
6376
6377         printf("finished dirtest1\n");
6378
6379         return correct;
6380 }
6381
6382 static bool run_error_map_extract(int dummy) {
6383
6384         static struct cli_state *c_dos;
6385         static struct cli_state *c_nt;
6386         NTSTATUS status;
6387
6388         uint32 error;
6389
6390         uint32 errnum;
6391         uint8 errclass;
6392
6393         NTSTATUS nt_status;
6394
6395         fstring user;
6396
6397         /* NT-Error connection */
6398
6399         disable_spnego = true;
6400         if (!(c_nt = open_nbt_connection())) {
6401                 disable_spnego = false;
6402                 return False;
6403         }
6404         disable_spnego = false;
6405
6406         status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
6407                                  PROTOCOL_NT1);
6408
6409         if (!NT_STATUS_IS_OK(status)) {
6410                 printf("%s rejected the NT-error negprot (%s)\n", host,
6411                        nt_errstr(status));
6412                 cli_shutdown(c_nt);
6413                 return False;
6414         }
6415
6416         status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
6417         if (!NT_STATUS_IS_OK(status)) {
6418                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
6419                 return False;
6420         }
6421
6422         /* DOS-Error connection */
6423
6424         disable_spnego = true;
6425         force_dos_errors = true;
6426         if (!(c_dos = open_nbt_connection())) {
6427                 disable_spnego = false;
6428                 force_dos_errors = false;
6429                 return False;
6430         }
6431         disable_spnego = false;
6432         force_dos_errors = false;
6433
6434         status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
6435                                  PROTOCOL_NT1);
6436         if (!NT_STATUS_IS_OK(status)) {
6437                 printf("%s rejected the DOS-error negprot (%s)\n", host,
6438                        nt_errstr(status));
6439                 cli_shutdown(c_dos);
6440                 return False;
6441         }
6442
6443         status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
6444         if (!NT_STATUS_IS_OK(status)) {
6445                 printf("%s rejected the DOS-error initial session setup (%s)\n",
6446                         host, nt_errstr(status));
6447                 return False;
6448         }
6449
6450         c_nt->map_dos_errors = false;
6451         c_dos->map_dos_errors = false;
6452
6453         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
6454                 fstr_sprintf(user, "%X", error);
6455
6456                 status = cli_session_setup(c_nt, user,
6457                                            password, strlen(password),
6458                                            password, strlen(password),
6459                                            workgroup);
6460                 if (NT_STATUS_IS_OK(status)) {
6461                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
6462                 }
6463
6464                 /* Case #1: 32-bit NT errors */
6465                 if (!NT_STATUS_IS_DOS(status)) {
6466                         nt_status = status;
6467                 } else {
6468                         printf("/** Dos error on NT connection! (%s) */\n", 
6469                                nt_errstr(status));
6470                         nt_status = NT_STATUS(0xc0000000);
6471                 }
6472
6473                 status = cli_session_setup(c_dos, user,
6474                                            password, strlen(password),
6475                                            password, strlen(password),
6476                                            workgroup);
6477                 if (NT_STATUS_IS_OK(status)) {
6478                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
6479                 }
6480
6481                 /* Case #1: 32-bit NT errors */
6482                 if (NT_STATUS_IS_DOS(status)) {
6483                         printf("/** NT error on DOS connection! (%s) */\n", 
6484                                nt_errstr(status));
6485                         errnum = errclass = 0;
6486                 } else {
6487                         errclass = NT_STATUS_DOS_CLASS(status);
6488                         errnum = NT_STATUS_DOS_CODE(status);
6489                 }
6490
6491                 if (NT_STATUS_V(nt_status) != error) { 
6492                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
6493                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
6494                                get_nt_error_c_code(talloc_tos(), nt_status));
6495                 }
6496
6497                 printf("\t{%s,\t%s,\t%s},\n", 
6498                        smb_dos_err_class(errclass), 
6499                        smb_dos_err_name(errclass, errnum), 
6500                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
6501         }
6502         return True;
6503 }
6504
6505 static bool run_sesssetup_bench(int dummy)
6506 {
6507         static struct cli_state *c;
6508         const char *fname = "\\file.dat";
6509         uint16_t fnum;
6510         NTSTATUS status;
6511         int i;
6512
6513         if (!torture_open_connection(&c, 0)) {
6514                 return false;
6515         }
6516
6517         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6518                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6519                               FILE_DELETE_ON_CLOSE, 0, &fnum);
6520         if (!NT_STATUS_IS_OK(status)) {
6521                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6522                 return false;
6523         }
6524
6525         for (i=0; i<torture_numops; i++) {
6526                 status = cli_session_setup(
6527                         c, username,
6528                         password, strlen(password),
6529                         password, strlen(password),
6530                         workgroup);
6531                 if (!NT_STATUS_IS_OK(status)) {
6532                         d_printf("(%s) cli_session_setup failed: %s\n",
6533                                  __location__, nt_errstr(status));
6534                         return false;
6535                 }
6536
6537                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
6538
6539                 status = cli_ulogoff(c);
6540                 if (!NT_STATUS_IS_OK(status)) {
6541                         d_printf("(%s) cli_ulogoff failed: %s\n",
6542                                  __location__, nt_errstr(status));
6543                         return false;
6544                 }
6545         }
6546
6547         return true;
6548 }
6549
6550 static bool subst_test(const char *str, const char *user, const char *domain,
6551                        uid_t uid, gid_t gid, const char *expected)
6552 {
6553         char *subst;
6554         bool result = true;
6555
6556         subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
6557
6558         if (strcmp(subst, expected) != 0) {
6559                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
6560                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
6561                        expected);
6562                 result = false;
6563         }
6564
6565         TALLOC_FREE(subst);
6566         return result;
6567 }
6568
6569 static void chain1_open_completion(struct tevent_req *req)
6570 {
6571         uint16_t fnum;
6572         NTSTATUS status;
6573         status = cli_openx_recv(req, &fnum);
6574         TALLOC_FREE(req);
6575
6576         d_printf("cli_openx_recv returned %s: %d\n",
6577                  nt_errstr(status),
6578                  NT_STATUS_IS_OK(status) ? fnum : -1);
6579 }
6580
6581 static void chain1_write_completion(struct tevent_req *req)
6582 {
6583         size_t written;
6584         NTSTATUS status;
6585         status = cli_write_andx_recv(req, &written);
6586         TALLOC_FREE(req);
6587
6588         d_printf("cli_write_andx_recv returned %s: %d\n",
6589                  nt_errstr(status),
6590                  NT_STATUS_IS_OK(status) ? (int)written : -1);
6591 }
6592
6593 static void chain1_close_completion(struct tevent_req *req)
6594 {
6595         NTSTATUS status;
6596         bool *done = (bool *)tevent_req_callback_data_void(req);
6597
6598         status = cli_close_recv(req);
6599         *done = true;
6600
6601         TALLOC_FREE(req);
6602
6603         d_printf("cli_close returned %s\n", nt_errstr(status));
6604 }
6605
6606 static bool run_chain1(int dummy)
6607 {
6608         struct cli_state *cli1;
6609         struct tevent_context *evt = samba_tevent_context_init(NULL);
6610         struct tevent_req *reqs[3], *smbreqs[3];
6611         bool done = false;
6612         const char *str = "foobar";
6613         NTSTATUS status;
6614
6615         printf("starting chain1 test\n");
6616         if (!torture_open_connection(&cli1, 0)) {
6617                 return False;
6618         }
6619
6620         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6621
6622         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, "\\test",
6623                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
6624         if (reqs[0] == NULL) return false;
6625         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
6626
6627
6628         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
6629                                         (const uint8_t *)str, 0, strlen(str)+1,
6630                                         smbreqs, 1, &smbreqs[1]);
6631         if (reqs[1] == NULL) return false;
6632         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
6633
6634         reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
6635         if (reqs[2] == NULL) return false;
6636         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
6637
6638         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
6639         if (!NT_STATUS_IS_OK(status)) {
6640                 return false;
6641         }
6642
6643         while (!done) {
6644                 tevent_loop_once(evt);
6645         }
6646
6647         torture_close_connection(cli1);
6648         return True;
6649 }
6650
6651 static void chain2_sesssetup_completion(struct tevent_req *req)
6652 {
6653         NTSTATUS status;
6654         status = cli_session_setup_guest_recv(req);
6655         d_printf("sesssetup returned %s\n", nt_errstr(status));
6656 }
6657
6658 static void chain2_tcon_completion(struct tevent_req *req)
6659 {
6660         bool *done = (bool *)tevent_req_callback_data_void(req);
6661         NTSTATUS status;
6662         status = cli_tcon_andx_recv(req);
6663         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
6664         *done = true;
6665 }
6666
6667 static bool run_chain2(int dummy)
6668 {
6669         struct cli_state *cli1;
6670         struct tevent_context *evt = samba_tevent_context_init(NULL);
6671         struct tevent_req *reqs[2], *smbreqs[2];
6672         bool done = false;
6673         NTSTATUS status;
6674
6675         printf("starting chain2 test\n");
6676         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
6677                                       port_to_use, SMB_SIGNING_DEFAULT, 0);
6678         if (!NT_STATUS_IS_OK(status)) {
6679                 return False;
6680         }
6681
6682         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6683
6684         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
6685                                                  &smbreqs[0]);
6686         if (reqs[0] == NULL) return false;
6687         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
6688
6689         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
6690                                        "?????", NULL, 0, &smbreqs[1]);
6691         if (reqs[1] == NULL) return false;
6692         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
6693
6694         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
6695         if (!NT_STATUS_IS_OK(status)) {
6696                 return false;
6697         }
6698
6699         while (!done) {
6700                 tevent_loop_once(evt);
6701         }
6702
6703         torture_close_connection(cli1);
6704         return True;
6705 }
6706
6707
6708 struct torture_createdel_state {
6709         struct tevent_context *ev;
6710         struct cli_state *cli;
6711 };
6712
6713 static void torture_createdel_created(struct tevent_req *subreq);
6714 static void torture_createdel_closed(struct tevent_req *subreq);
6715
6716 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
6717                                                  struct tevent_context *ev,
6718                                                  struct cli_state *cli,
6719                                                  const char *name)
6720 {
6721         struct tevent_req *req, *subreq;
6722         struct torture_createdel_state *state;
6723
6724         req = tevent_req_create(mem_ctx, &state,
6725                                 struct torture_createdel_state);
6726         if (req == NULL) {
6727                 return NULL;
6728         }
6729         state->ev = ev;
6730         state->cli = cli;
6731
6732         subreq = cli_ntcreate_send(
6733                 state, ev, cli, name, 0,
6734                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
6735                 FILE_ATTRIBUTE_NORMAL,
6736                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6737                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
6738
6739         if (tevent_req_nomem(subreq, req)) {
6740                 return tevent_req_post(req, ev);
6741         }
6742         tevent_req_set_callback(subreq, torture_createdel_created, req);
6743         return req;
6744 }
6745
6746 static void torture_createdel_created(struct tevent_req *subreq)
6747 {
6748         struct tevent_req *req = tevent_req_callback_data(
6749                 subreq, struct tevent_req);
6750         struct torture_createdel_state *state = tevent_req_data(
6751                 req, struct torture_createdel_state);
6752         NTSTATUS status;
6753         uint16_t fnum;
6754
6755         status = cli_ntcreate_recv(subreq, &fnum);
6756         TALLOC_FREE(subreq);
6757         if (tevent_req_nterror(req, status)) {
6758                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
6759                            nt_errstr(status)));
6760                 return;
6761         }
6762
6763         subreq = cli_close_send(state, state->ev, state->cli, fnum);
6764         if (tevent_req_nomem(subreq, req)) {
6765                 return;
6766         }
6767         tevent_req_set_callback(subreq, torture_createdel_closed, req);
6768 }
6769
6770 static void torture_createdel_closed(struct tevent_req *subreq)
6771 {
6772         struct tevent_req *req = tevent_req_callback_data(
6773                 subreq, struct tevent_req);
6774         NTSTATUS status;
6775
6776         status = cli_close_recv(subreq);
6777         if (tevent_req_nterror(req, status)) {
6778                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
6779                 return;
6780         }
6781         tevent_req_done(req);
6782 }
6783
6784 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
6785 {
6786         return tevent_req_simple_recv_ntstatus(req);
6787 }
6788
6789 struct torture_createdels_state {
6790         struct tevent_context *ev;
6791         struct cli_state *cli;
6792         const char *base_name;
6793         int sent;
6794         int received;
6795         int num_files;
6796         struct tevent_req **reqs;
6797 };
6798
6799 static void torture_createdels_done(struct tevent_req *subreq);
6800
6801 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
6802                                                   struct tevent_context *ev,
6803                                                   struct cli_state *cli,
6804                                                   const char *base_name,
6805                                                   int num_parallel,
6806                                                   int num_files)
6807 {
6808         struct tevent_req *req;
6809         struct torture_createdels_state *state;
6810         int i;
6811
6812         req = tevent_req_create(mem_ctx, &state,
6813                                 struct torture_createdels_state);
6814         if (req == NULL) {
6815                 return NULL;
6816         }
6817         state->ev = ev;
6818         state->cli = cli;
6819         state->base_name = talloc_strdup(state, base_name);
6820         if (tevent_req_nomem(state->base_name, req)) {
6821                 return tevent_req_post(req, ev);
6822         }
6823         state->num_files = MAX(num_parallel, num_files);
6824         state->sent = 0;
6825         state->received = 0;
6826
6827         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
6828         if (tevent_req_nomem(state->reqs, req)) {
6829                 return tevent_req_post(req, ev);
6830         }
6831
6832         for (i=0; i<num_parallel; i++) {
6833                 char *name;
6834
6835                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6836                                        state->sent);
6837                 if (tevent_req_nomem(name, req)) {
6838                         return tevent_req_post(req, ev);
6839                 }
6840                 state->reqs[i] = torture_createdel_send(
6841                         state->reqs, state->ev, state->cli, name);
6842                 if (tevent_req_nomem(state->reqs[i], req)) {
6843                         return tevent_req_post(req, ev);
6844                 }
6845                 name = talloc_move(state->reqs[i], &name);
6846                 tevent_req_set_callback(state->reqs[i],
6847                                         torture_createdels_done, req);
6848                 state->sent += 1;
6849         }
6850         return req;
6851 }
6852
6853 static void torture_createdels_done(struct tevent_req *subreq)
6854 {
6855         struct tevent_req *req = tevent_req_callback_data(
6856                 subreq, struct tevent_req);
6857         struct torture_createdels_state *state = tevent_req_data(
6858                 req, struct torture_createdels_state);
6859         size_t num_parallel = talloc_array_length(state->reqs);
6860         NTSTATUS status;
6861         char *name;
6862         int i;
6863
6864         status = torture_createdel_recv(subreq);
6865         if (!NT_STATUS_IS_OK(status)){
6866                 DEBUG(10, ("torture_createdel_recv returned %s\n",
6867                            nt_errstr(status)));
6868                 TALLOC_FREE(subreq);
6869                 tevent_req_nterror(req, status);
6870                 return;
6871         }
6872
6873         for (i=0; i<num_parallel; i++) {
6874                 if (subreq == state->reqs[i]) {
6875                         break;
6876                 }
6877         }
6878         if (i == num_parallel) {
6879                 DEBUG(10, ("received something we did not send\n"));
6880                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
6881                 return;
6882         }
6883         TALLOC_FREE(state->reqs[i]);
6884
6885         if (state->sent >= state->num_files) {
6886                 tevent_req_done(req);
6887                 return;
6888         }
6889
6890         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6891                                state->sent);
6892         if (tevent_req_nomem(name, req)) {
6893                 return;
6894         }
6895         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
6896                                                 state->cli, name);
6897         if (tevent_req_nomem(state->reqs[i], req)) {
6898                 return;
6899         }
6900         name = talloc_move(state->reqs[i], &name);
6901         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
6902         state->sent += 1;
6903 }
6904
6905 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
6906 {
6907         return tevent_req_simple_recv_ntstatus(req);
6908 }
6909
6910 struct swallow_notify_state {
6911         struct tevent_context *ev;
6912         struct cli_state *cli;
6913         uint16_t fnum;
6914         uint32_t completion_filter;
6915         bool recursive;
6916         bool (*fn)(uint32_t action, const char *name, void *priv);
6917         void *priv;
6918 };
6919
6920 static void swallow_notify_done(struct tevent_req *subreq);
6921
6922 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
6923                                               struct tevent_context *ev,
6924                                               struct cli_state *cli,
6925                                               uint16_t fnum,
6926                                               uint32_t completion_filter,
6927                                               bool recursive,
6928                                               bool (*fn)(uint32_t action,
6929                                                          const char *name,
6930                                                          void *priv),
6931                                               void *priv)
6932 {
6933         struct tevent_req *req, *subreq;
6934         struct swallow_notify_state *state;
6935
6936         req = tevent_req_create(mem_ctx, &state,
6937                                 struct swallow_notify_state);
6938         if (req == NULL) {
6939                 return NULL;
6940         }
6941         state->ev = ev;
6942         state->cli = cli;
6943         state->fnum = fnum;
6944         state->completion_filter = completion_filter;
6945         state->recursive = recursive;
6946         state->fn = fn;
6947         state->priv = priv;
6948
6949         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6950                                  0xffff, state->completion_filter,
6951                                  state->recursive);
6952         if (tevent_req_nomem(subreq, req)) {
6953                 return tevent_req_post(req, ev);
6954         }
6955         tevent_req_set_callback(subreq, swallow_notify_done, req);
6956         return req;
6957 }
6958
6959 static void swallow_notify_done(struct tevent_req *subreq)
6960 {
6961         struct tevent_req *req = tevent_req_callback_data(
6962                 subreq, struct tevent_req);
6963         struct swallow_notify_state *state = tevent_req_data(
6964                 req, struct swallow_notify_state);
6965         NTSTATUS status;
6966         uint32_t i, num_changes;
6967         struct notify_change *changes;
6968
6969         status = cli_notify_recv(subreq, state, &num_changes, &changes);
6970         TALLOC_FREE(subreq);
6971         if (!NT_STATUS_IS_OK(status)) {
6972                 DEBUG(10, ("cli_notify_recv returned %s\n",
6973                            nt_errstr(status)));
6974                 tevent_req_nterror(req, status);
6975                 return;
6976         }
6977
6978         for (i=0; i<num_changes; i++) {
6979                 state->fn(changes[i].action, changes[i].name, state->priv);
6980         }
6981         TALLOC_FREE(changes);
6982
6983         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6984                                  0xffff, state->completion_filter,
6985                                  state->recursive);
6986         if (tevent_req_nomem(subreq, req)) {
6987                 return;
6988         }
6989         tevent_req_set_callback(subreq, swallow_notify_done, req);
6990 }
6991
6992 static bool print_notifies(uint32_t action, const char *name, void *priv)
6993 {
6994         if (DEBUGLEVEL > 5) {
6995                 d_printf("%d %s\n", (int)action, name);
6996         }
6997         return true;
6998 }
6999
7000 static void notify_bench_done(struct tevent_req *req)
7001 {
7002         int *num_finished = (int *)tevent_req_callback_data_void(req);
7003         *num_finished += 1;
7004 }
7005
7006 static bool run_notify_bench(int dummy)
7007 {
7008         const char *dname = "\\notify-bench";
7009         struct tevent_context *ev;
7010         NTSTATUS status;
7011         uint16_t dnum;
7012         struct tevent_req *req1;
7013         struct tevent_req *req2 = NULL;
7014         int i, num_unc_names;
7015         int num_finished = 0;
7016
7017         printf("starting notify-bench test\n");
7018
7019         if (use_multishare_conn) {
7020                 char **unc_list;
7021                 unc_list = file_lines_load(multishare_conn_fname,
7022                                            &num_unc_names, 0, NULL);
7023                 if (!unc_list || num_unc_names <= 0) {
7024                         d_printf("Failed to load unc names list from '%s'\n",
7025                                  multishare_conn_fname);
7026                         return false;
7027                 }
7028                 TALLOC_FREE(unc_list);
7029         } else {
7030                 num_unc_names = 1;
7031         }
7032
7033         ev = samba_tevent_context_init(talloc_tos());
7034         if (ev == NULL) {
7035                 d_printf("tevent_context_init failed\n");
7036                 return false;
7037         }
7038
7039         for (i=0; i<num_unc_names; i++) {
7040                 struct cli_state *cli;
7041                 char *base_fname;
7042
7043                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
7044                                              dname, i);
7045                 if (base_fname == NULL) {
7046                         return false;
7047                 }
7048
7049                 if (!torture_open_connection(&cli, i)) {
7050                         return false;
7051                 }
7052
7053                 status = cli_ntcreate(cli, dname, 0,
7054                                       MAXIMUM_ALLOWED_ACCESS,
7055                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
7056                                       FILE_SHARE_DELETE,
7057                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
7058                                       &dnum);
7059
7060                 if (!NT_STATUS_IS_OK(status)) {
7061                         d_printf("Could not create %s: %s\n", dname,
7062                                  nt_errstr(status));
7063                         return false;
7064                 }
7065
7066                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
7067                                            FILE_NOTIFY_CHANGE_FILE_NAME |
7068                                            FILE_NOTIFY_CHANGE_DIR_NAME |
7069                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
7070                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
7071                                            false, print_notifies, NULL);
7072                 if (req1 == NULL) {
7073                         d_printf("Could not create notify request\n");
7074                         return false;
7075                 }
7076
7077                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
7078                                                base_fname, 10, torture_numops);
7079                 if (req2 == NULL) {
7080                         d_printf("Could not create createdels request\n");
7081                         return false;
7082                 }
7083                 TALLOC_FREE(base_fname);
7084
7085                 tevent_req_set_callback(req2, notify_bench_done,
7086                                         &num_finished);
7087         }
7088
7089         while (num_finished < num_unc_names) {
7090                 int ret;
7091                 ret = tevent_loop_once(ev);
7092                 if (ret != 0) {
7093                         d_printf("tevent_loop_once failed\n");
7094                         return false;
7095                 }
7096         }
7097
7098         if (!tevent_req_poll(req2, ev)) {
7099                 d_printf("tevent_req_poll failed\n");
7100         }
7101
7102         status = torture_createdels_recv(req2);
7103         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
7104
7105         return true;
7106 }
7107
7108 static bool run_mangle1(int dummy)
7109 {
7110         struct cli_state *cli;
7111         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
7112         uint16_t fnum;
7113         fstring alt_name;
7114         NTSTATUS status;
7115         time_t change_time, access_time, write_time;
7116         off_t size;
7117         uint16_t mode;
7118
7119         printf("starting mangle1 test\n");
7120         if (!torture_open_connection(&cli, 0)) {
7121                 return False;
7122         }
7123
7124         smbXcli_conn_set_sockopt(cli->conn, sockops);
7125
7126         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7127                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7128                               0, 0, &fnum);
7129         if (!NT_STATUS_IS_OK(status)) {
7130                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7131                 return false;
7132         }
7133         cli_close(cli, fnum);
7134
7135         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
7136         if (!NT_STATUS_IS_OK(status)) {
7137                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
7138                          nt_errstr(status));
7139                 return false;
7140         }
7141         d_printf("alt_name: %s\n", alt_name);
7142
7143         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
7144         if (!NT_STATUS_IS_OK(status)) {
7145                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
7146                          nt_errstr(status));
7147                 return false;
7148         }
7149         cli_close(cli, fnum);
7150
7151         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
7152                                 &write_time, &size, &mode);
7153         if (!NT_STATUS_IS_OK(status)) {
7154                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
7155                          nt_errstr(status));
7156                 return false;
7157         }
7158
7159         return true;
7160 }
7161
7162 static size_t null_source(uint8_t *buf, size_t n, void *priv)
7163 {
7164         size_t *to_pull = (size_t *)priv;
7165         size_t thistime = *to_pull;
7166
7167         thistime = MIN(thistime, n);
7168         if (thistime == 0) {
7169                 return 0;
7170         }
7171
7172         memset(buf, 0, thistime);
7173         *to_pull -= thistime;
7174         return thistime;
7175 }
7176
7177 static bool run_windows_write(int dummy)
7178 {
7179         struct cli_state *cli1;
7180         uint16_t fnum;
7181         int i;
7182         bool ret = false;
7183         const char *fname = "\\writetest.txt";
7184         struct timeval start_time;
7185         double seconds;
7186         double kbytes;
7187         NTSTATUS status;
7188
7189         printf("starting windows_write test\n");
7190         if (!torture_open_connection(&cli1, 0)) {
7191                 return False;
7192         }
7193
7194         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7195         if (!NT_STATUS_IS_OK(status)) {
7196                 printf("open failed (%s)\n", nt_errstr(status));
7197                 return False;
7198         }
7199
7200         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7201
7202         start_time = timeval_current();
7203
7204         for (i=0; i<torture_numops; i++) {
7205                 uint8_t c = 0;
7206                 off_t start = i * torture_blocksize;
7207                 size_t to_pull = torture_blocksize - 1;
7208
7209                 status = cli_writeall(cli1, fnum, 0, &c,
7210                                       start + torture_blocksize - 1, 1, NULL);
7211                 if (!NT_STATUS_IS_OK(status)) {
7212                         printf("cli_write failed: %s\n", nt_errstr(status));
7213                         goto fail;
7214                 }
7215
7216                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
7217                                   null_source, &to_pull);
7218                 if (!NT_STATUS_IS_OK(status)) {
7219                         printf("cli_push returned: %s\n", nt_errstr(status));
7220                         goto fail;
7221                 }
7222         }
7223
7224         seconds = timeval_elapsed(&start_time);
7225         kbytes = (double)torture_blocksize * torture_numops;
7226         kbytes /= 1024;
7227
7228         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
7229                (double)seconds, (int)(kbytes/seconds));
7230
7231         ret = true;
7232  fail:
7233         cli_close(cli1, fnum);
7234         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7235         torture_close_connection(cli1);
7236         return ret;
7237 }
7238
7239 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
7240 {
7241         size_t max_pdu = 0x1FFFF;
7242
7243         if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
7244                 max_pdu = 0xFFFFFF;
7245         }
7246
7247         if (smb1cli_conn_signing_is_active(cli->conn)) {
7248                 max_pdu = 0x1FFFF;
7249         }
7250
7251         if (smb1cli_conn_encryption_on(cli->conn)) {
7252                 max_pdu = CLI_BUFFER_SIZE;
7253         }
7254
7255         if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
7256                 len_requested &= 0xFFFF;
7257         }
7258
7259         return MIN(len_requested, max_pdu - (MIN_SMB_SIZE + VWV(12)));
7260 }
7261
7262 static bool check_read_call(struct cli_state *cli,
7263                             uint16_t fnum,
7264                             uint8_t *buf,
7265                             size_t len_requested)
7266 {
7267         NTSTATUS status;
7268         struct tevent_req *subreq = NULL;
7269         ssize_t len_read = 0;
7270         size_t len_expected = 0;
7271         struct tevent_context *ev = NULL;
7272
7273         ev = samba_tevent_context_init(talloc_tos());
7274         if (ev == NULL) {
7275                 return false;
7276         }
7277
7278         subreq = cli_read_andx_send(talloc_tos(),
7279                                     ev,
7280                                     cli,
7281                                     fnum,
7282                                     0,
7283                                     len_requested);
7284
7285         if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
7286                 return false;
7287         }
7288
7289         status = cli_read_andx_recv(subreq, &len_read, &buf);
7290         if (!NT_STATUS_IS_OK(status)) {
7291                 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
7292                 return false;
7293         }
7294
7295         TALLOC_FREE(subreq);
7296         TALLOC_FREE(ev);
7297
7298         len_expected = calc_expected_return(cli, len_requested);
7299
7300         if (len_expected > 0x10000 && len_read == 0x10000) {
7301                 /* Windows servers only return a max of 0x10000,
7302                    doesn't matter if you set CAP_LARGE_READX in
7303                    the client sessionsetupX call or not. */
7304                 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
7305                         (unsigned int)len_requested);
7306         } else if (len_read != len_expected) {
7307                 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
7308                         (unsigned int)len_requested,
7309                         (unsigned int)len_read,
7310                         (unsigned int)len_expected);
7311                 return false;
7312         } else {
7313                 d_printf("Correct read reply.\n");
7314         }
7315
7316         return true;
7317 }
7318
7319 /* Test large readX variants. */
7320 static bool large_readx_tests(struct cli_state *cli,
7321                                 uint16_t fnum,
7322                                 uint8_t *buf)
7323 {
7324         /* A read of 0xFFFF0001 should *always* return 1 byte. */
7325         if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
7326                 return false;
7327         }
7328         /* A read of 0x10000 should return 0x10000 bytes. */
7329         if (check_read_call(cli, fnum, buf,    0x10000) == false) {
7330                 return false;
7331         }
7332         /* A read of 0x10000 should return 0x10001 bytes. */
7333         if (check_read_call(cli, fnum, buf,    0x10001) == false) {
7334                 return false;
7335         }
7336         /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
7337            the requested number of bytes. */
7338         if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
7339                 return false;
7340         }
7341         /* A read of 1MB should return 1MB bytes (on Samba). */
7342         if (check_read_call(cli, fnum, buf,   0x100000) == false) {
7343                 return false;
7344         }
7345
7346         if (check_read_call(cli, fnum, buf,    0x20001) == false) {
7347                 return false;
7348         }
7349         if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
7350                 return false;
7351         }
7352         if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
7353                 return false;
7354         }
7355         return true;
7356 }
7357
7358 static bool run_large_readx(int dummy)
7359 {
7360         uint8_t *buf = NULL;
7361         struct cli_state *cli1 = NULL;
7362         struct cli_state *cli2 = NULL;
7363         bool correct = false;
7364         const char *fname = "\\large_readx.dat";
7365         NTSTATUS status;
7366         uint16_t fnum1 = UINT16_MAX;
7367         uint32_t normal_caps = 0;
7368         size_t file_size = 20*1024*1024;
7369         TALLOC_CTX *frame = talloc_stackframe();
7370         size_t i;
7371         struct {
7372                 const char *name;
7373                 enum smb_signing_setting signing_setting;
7374                 enum protocol_types protocol;
7375         } runs[] = {
7376                 {
7377                         .name = "NT1",
7378                         .signing_setting = SMB_SIGNING_IF_REQUIRED,
7379                         .protocol = PROTOCOL_NT1,
7380                 },{
7381                         .name = "NT1 - SIGNING_REQUIRED",
7382                         .signing_setting = SMB_SIGNING_REQUIRED,
7383                         .protocol = PROTOCOL_NT1,
7384                 },
7385         };
7386
7387         printf("starting large_readx test\n");
7388
7389         if (!torture_open_connection(&cli1, 0)) {
7390                 goto out;
7391         }
7392
7393         normal_caps = smb1cli_conn_capabilities(cli1->conn);
7394
7395         if (!(normal_caps & CAP_LARGE_READX)) {
7396                 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
7397                         (unsigned int)normal_caps);
7398                 goto out;
7399         }
7400
7401         /* Create a file of size 4MB. */
7402         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
7403                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7404                         0, 0, &fnum1);
7405
7406         if (!NT_STATUS_IS_OK(status)) {
7407                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7408                 goto out;
7409         }
7410
7411         /* Write file_size bytes. */
7412         buf = talloc_zero_array(frame, uint8_t, file_size);
7413         if (buf == NULL) {
7414                 goto out;
7415         }
7416
7417         status = cli_writeall(cli1,
7418                               fnum1,
7419                               0,
7420                               buf,
7421                               0,
7422                               file_size,
7423                               NULL);
7424         if (!NT_STATUS_IS_OK(status)) {
7425                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
7426                 goto out;
7427         }
7428
7429         status = cli_close(cli1, fnum1);
7430         if (!NT_STATUS_IS_OK(status)) {
7431                 d_printf("cli_close failed: %s\n", nt_errstr(status));
7432                 goto out;
7433         }
7434
7435         fnum1 = UINT16_MAX;
7436
7437         for (i=0; i < ARRAY_SIZE(runs); i++) {
7438                 enum smb_signing_setting saved_signing_setting = signing_state;
7439                 uint16_t fnum2 = -1;
7440
7441                 if (do_encrypt &&
7442                     (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
7443                 {
7444                         d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
7445                         continue;
7446                 }
7447
7448                 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
7449
7450                 signing_state = runs[i].signing_setting;
7451                 cli2 = open_nbt_connection();
7452                 signing_state = saved_signing_setting;
7453                 if (cli2 == NULL) {
7454                         goto out;
7455                 }
7456
7457                 status = smbXcli_negprot(cli2->conn,
7458                                          cli2->timeout,
7459                                          runs[i].protocol,
7460                                          runs[i].protocol);
7461                 if (!NT_STATUS_IS_OK(status)) {
7462                         goto out;
7463                 }
7464
7465                 status = cli_session_setup(cli2,
7466                                         username,
7467                                         password,
7468                                         strlen(password)+1,
7469                                         password,
7470                                         strlen(password)+1,
7471                                         workgroup);
7472                 if (!NT_STATUS_IS_OK(status)) {
7473                         goto out;
7474                 }
7475
7476                 status = cli_tree_connect(cli2,
7477                                         share,
7478                                         "?????",
7479                                         password,
7480                                         strlen(password)+1);
7481                 if (!NT_STATUS_IS_OK(status)) {
7482                         goto out;
7483                 }
7484
7485                 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
7486
7487                 normal_caps = smb1cli_conn_capabilities(cli2->conn);
7488
7489                 if (!(normal_caps & CAP_LARGE_READX)) {
7490                         d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
7491                                 (unsigned int)normal_caps);
7492                         goto out;
7493                 }
7494
7495                 if (do_encrypt) {
7496                         if (force_cli_encryption(cli2, share) == false) {
7497                                 goto out;
7498                         }
7499                 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
7500                         uint16_t major, minor;
7501                         uint32_t caplow, caphigh;
7502
7503                         status = cli_unix_extensions_version(cli2,
7504                                                              &major, &minor,
7505                                                              &caplow, &caphigh);
7506                         if (!NT_STATUS_IS_OK(status)) {
7507                                 goto out;
7508                         }
7509                 }
7510
7511                 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
7512                                 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
7513                                 0, 0, &fnum2);
7514                 if (!NT_STATUS_IS_OK(status)) {
7515                         d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
7516                         goto out;
7517                 }
7518
7519                 /* All reads must return less than file_size bytes. */
7520                 if (!large_readx_tests(cli2, fnum2, buf)) {
7521                         goto out;
7522                 }
7523
7524                 status = cli_close(cli2, fnum2);
7525                 if (!NT_STATUS_IS_OK(status)) {
7526                         d_printf("cli_close failed: %s\n", nt_errstr(status));
7527                         goto out;
7528                 }
7529                 fnum2 = -1;
7530
7531                 if (!torture_close_connection(cli2)) {
7532                         goto out;
7533                 }
7534                 cli2 = NULL;
7535         }
7536
7537         correct = true;
7538         printf("Success on large_readx test\n");
7539
7540   out:
7541
7542         if (cli2) {
7543                 if (!torture_close_connection(cli2)) {
7544                         correct = false;
7545                 }
7546         }
7547
7548         if (cli1) {
7549                 if (fnum1 != UINT16_MAX) {
7550                         status = cli_close(cli1, fnum1);
7551                         if (!NT_STATUS_IS_OK(status)) {
7552                                 d_printf("cli_close failed: %s\n", nt_errstr(status));
7553                         }
7554                         fnum1 = UINT16_MAX;
7555                 }
7556
7557                 status = cli_unlink(cli1, fname,
7558                                     FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7559                 if (!NT_STATUS_IS_OK(status)) {
7560                         printf("unlink failed (%s)\n", nt_errstr(status));
7561                 }
7562
7563                 if (!torture_close_connection(cli1)) {
7564                         correct = false;
7565                 }
7566         }
7567
7568         TALLOC_FREE(frame);
7569
7570         printf("finished large_readx test\n");
7571         return correct;
7572 }
7573
7574 static bool run_cli_echo(int dummy)
7575 {
7576         struct cli_state *cli;
7577         NTSTATUS status;
7578
7579         printf("starting cli_echo test\n");
7580         if (!torture_open_connection(&cli, 0)) {
7581                 return false;
7582         }
7583         smbXcli_conn_set_sockopt(cli->conn, sockops);
7584
7585         status = cli_echo(cli, 5, data_blob_const("hello", 5));
7586
7587         d_printf("cli_echo returned %s\n", nt_errstr(status));
7588
7589         torture_close_connection(cli);
7590         return NT_STATUS_IS_OK(status);
7591 }
7592
7593 static bool run_uid_regression_test(int dummy)
7594 {
7595         static struct cli_state *cli;
7596         int16_t old_vuid;
7597         int16_t old_cnum;
7598         bool correct = True;
7599         NTSTATUS status;
7600
7601         printf("starting uid regression test\n");
7602
7603         if (!torture_open_connection(&cli, 0)) {
7604                 return False;
7605         }
7606
7607         smbXcli_conn_set_sockopt(cli->conn, sockops);
7608
7609         /* Ok - now save then logoff our current user. */
7610         old_vuid = cli_state_get_uid(cli);
7611
7612         status = cli_ulogoff(cli);
7613         if (!NT_STATUS_IS_OK(status)) {
7614                 d_printf("(%s) cli_ulogoff failed: %s\n",
7615                          __location__, nt_errstr(status));
7616                 correct = false;
7617                 goto out;
7618         }
7619
7620         cli_state_set_uid(cli, old_vuid);
7621
7622         /* Try an operation. */
7623         status = cli_mkdir(cli, "\\uid_reg_test");
7624         if (NT_STATUS_IS_OK(status)) {
7625                 d_printf("(%s) cli_mkdir succeeded\n",
7626                          __location__);
7627                 correct = false;
7628                 goto out;
7629         } else {
7630                 /* Should be bad uid. */
7631                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
7632                                  NT_STATUS_USER_SESSION_DELETED)) {
7633                         correct = false;
7634                         goto out;
7635                 }
7636         }
7637
7638         old_cnum = cli_state_get_tid(cli);
7639
7640         /* Now try a SMBtdis with the invald vuid set to zero. */
7641         cli_state_set_uid(cli, 0);
7642
7643         /* This should succeed. */
7644         status = cli_tdis(cli);
7645
7646         if (NT_STATUS_IS_OK(status)) {
7647                 d_printf("First tdis with invalid vuid should succeed.\n");
7648         } else {
7649                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
7650                 correct = false;
7651                 goto out;
7652         }
7653
7654         cli_state_set_uid(cli, old_vuid);
7655         cli_state_set_tid(cli, old_cnum);
7656
7657         /* This should fail. */
7658         status = cli_tdis(cli);
7659         if (NT_STATUS_IS_OK(status)) {
7660                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
7661                 correct = false;
7662                 goto out;
7663         } else {
7664                 /* Should be bad tid. */
7665                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
7666                                 NT_STATUS_NETWORK_NAME_DELETED)) {
7667                         correct = false;
7668                         goto out;
7669                 }
7670         }
7671
7672         cli_rmdir(cli, "\\uid_reg_test");
7673
7674   out:
7675
7676         cli_shutdown(cli);
7677         return correct;
7678 }
7679
7680
7681 static const char *illegal_chars = "*\\/?<>|\":";
7682 static char force_shortname_chars[] = " +,.[];=\177";
7683
7684 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
7685                              const char *mask, void *state)
7686 {
7687         struct cli_state *pcli = (struct cli_state *)state;
7688         fstring fname;
7689         NTSTATUS status = NT_STATUS_OK;
7690
7691         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
7692
7693         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7694                 return NT_STATUS_OK;
7695
7696         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7697                 status = cli_rmdir(pcli, fname);
7698                 if (!NT_STATUS_IS_OK(status)) {
7699                         printf("del_fn: failed to rmdir %s\n,", fname );
7700                 }
7701         } else {
7702                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7703                 if (!NT_STATUS_IS_OK(status)) {
7704                         printf("del_fn: failed to unlink %s\n,", fname );
7705                 }
7706         }
7707         return status;
7708 }
7709
7710 struct sn_state {
7711         int matched;
7712         int i;
7713         bool val;
7714 };
7715
7716 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
7717                               const char *name, void *state)
7718 {
7719         struct sn_state *s = (struct sn_state  *)state;
7720         int i = s->i;
7721
7722 #if 0
7723         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
7724                 i, finfo->name, finfo->short_name);
7725 #endif
7726
7727         if (strchr(force_shortname_chars, i)) {
7728                 if (!finfo->short_name) {
7729                         /* Shortname not created when it should be. */
7730                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
7731                                 __location__, finfo->name, i);
7732                         s->val = true;
7733                 }
7734         } else if (finfo->short_name){
7735                 /* Shortname created when it should not be. */
7736                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
7737                         __location__, finfo->short_name, finfo->name);
7738                 s->val = true;
7739         }
7740         s->matched += 1;
7741         return NT_STATUS_OK;
7742 }
7743
7744 static bool run_shortname_test(int dummy)
7745 {
7746         static struct cli_state *cli;
7747         bool correct = True;
7748         int i;
7749         struct sn_state s;
7750         char fname[40];
7751         NTSTATUS status;
7752
7753         printf("starting shortname test\n");
7754
7755         if (!torture_open_connection(&cli, 0)) {
7756                 return False;
7757         }
7758
7759         smbXcli_conn_set_sockopt(cli->conn, sockops);
7760
7761         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7762         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7763         cli_rmdir(cli, "\\shortname");
7764
7765         status = cli_mkdir(cli, "\\shortname");
7766         if (!NT_STATUS_IS_OK(status)) {
7767                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
7768                         __location__, nt_errstr(status));
7769                 correct = false;
7770                 goto out;
7771         }
7772
7773         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
7774                 correct = false;
7775                 goto out;
7776         }
7777         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
7778                 correct = false;
7779                 goto out;
7780         }
7781
7782         s.val = false;
7783
7784         for (i = 32; i < 128; i++) {
7785                 uint16_t fnum = (uint16_t)-1;
7786
7787                 s.i = i;
7788
7789                 if (strchr(illegal_chars, i)) {
7790                         continue;
7791                 }
7792                 fname[15] = i;
7793
7794                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
7795                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
7796                 if (!NT_STATUS_IS_OK(status)) {
7797                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
7798                                 __location__, fname, nt_errstr(status));
7799                         correct = false;
7800                         goto out;
7801                 }
7802                 cli_close(cli, fnum);
7803
7804                 s.matched = 0;
7805                 status = cli_list(cli, "\\shortname\\test*.*", 0,
7806                                   shortname_list_fn, &s);
7807                 if (s.matched != 1) {
7808                         d_printf("(%s) failed to list %s: %s\n",
7809                                 __location__, fname, nt_errstr(status));
7810                         correct = false;
7811                         goto out;
7812                 }
7813
7814                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7815                 if (!NT_STATUS_IS_OK(status)) {
7816                         d_printf("(%s) failed to delete %s: %s\n",
7817                                 __location__, fname, nt_errstr(status));
7818                         correct = false;
7819                         goto out;
7820                 }
7821
7822                 if (s.val) {
7823                         correct = false;
7824                         goto out;
7825                 }
7826         }
7827
7828   out:
7829
7830         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7831         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7832         cli_rmdir(cli, "\\shortname");
7833         torture_close_connection(cli);
7834         return correct;
7835 }
7836
7837 static void pagedsearch_cb(struct tevent_req *req)
7838 {
7839         int rc;
7840         struct tldap_message *msg;
7841         char *dn;
7842
7843         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
7844         if (rc != TLDAP_SUCCESS) {
7845                 d_printf("tldap_search_paged_recv failed: %s\n",
7846                          tldap_err2string(rc));
7847                 return;
7848         }
7849         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
7850                 TALLOC_FREE(msg);
7851                 return;
7852         }
7853         if (!tldap_entry_dn(msg, &dn)) {
7854                 d_printf("tldap_entry_dn failed\n");
7855                 return;
7856         }
7857         d_printf("%s\n", dn);
7858         TALLOC_FREE(msg);
7859 }
7860
7861 static bool run_tldap(int dummy)
7862 {
7863         struct tldap_context *ld;
7864         int fd, rc;
7865         NTSTATUS status;
7866         struct sockaddr_storage addr;
7867         struct tevent_context *ev;
7868         struct tevent_req *req;
7869         char *basedn;
7870         const char *filter;
7871
7872         if (!resolve_name(host, &addr, 0, false)) {
7873                 d_printf("could not find host %s\n", host);
7874                 return false;
7875         }
7876         status = open_socket_out(&addr, 389, 9999, &fd);
7877         if (!NT_STATUS_IS_OK(status)) {
7878                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
7879                 return false;
7880         }
7881
7882         ld = tldap_context_create(talloc_tos(), fd);
7883         if (ld == NULL) {
7884                 close(fd);
7885                 d_printf("tldap_context_create failed\n");
7886                 return false;
7887         }
7888
7889         rc = tldap_fetch_rootdse(ld);
7890         if (rc != TLDAP_SUCCESS) {
7891                 d_printf("tldap_fetch_rootdse failed: %s\n",
7892                          tldap_errstr(talloc_tos(), ld, rc));
7893                 return false;
7894         }
7895
7896         basedn = tldap_talloc_single_attribute(
7897                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
7898         if (basedn == NULL) {
7899                 d_printf("no defaultNamingContext\n");
7900                 return false;
7901         }
7902         d_printf("defaultNamingContext: %s\n", basedn);
7903
7904         ev = samba_tevent_context_init(talloc_tos());
7905         if (ev == NULL) {
7906                 d_printf("tevent_context_init failed\n");
7907                 return false;
7908         }
7909
7910         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
7911                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
7912                                       NULL, 0, 0,
7913                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
7914         if (req == NULL) {
7915                 d_printf("tldap_search_paged_send failed\n");
7916                 return false;
7917         }
7918         tevent_req_set_callback(req, pagedsearch_cb, NULL);
7919
7920         tevent_req_poll(req, ev);
7921
7922         TALLOC_FREE(req);
7923
7924         /* test search filters against rootDSE */
7925         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
7926                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
7927
7928         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
7929                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
7930                           talloc_tos(), NULL, NULL);
7931         if (rc != TLDAP_SUCCESS) {
7932                 d_printf("tldap_search with complex filter failed: %s\n",
7933                          tldap_errstr(talloc_tos(), ld, rc));
7934                 return false;
7935         }
7936
7937         TALLOC_FREE(ld);
7938         return true;
7939 }
7940
7941 /* Torture test to ensure no regression of :
7942 https://bugzilla.samba.org/show_bug.cgi?id=7084
7943 */
7944
7945 static bool run_dir_createtime(int dummy)
7946 {
7947         struct cli_state *cli;
7948         const char *dname = "\\testdir";
7949         const char *fname = "\\testdir\\testfile";
7950         NTSTATUS status;
7951         struct timespec create_time;
7952         struct timespec create_time1;
7953         uint16_t fnum;
7954         bool ret = false;
7955
7956         if (!torture_open_connection(&cli, 0)) {
7957                 return false;
7958         }
7959
7960         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7961         cli_rmdir(cli, dname);
7962
7963         status = cli_mkdir(cli, dname);
7964         if (!NT_STATUS_IS_OK(status)) {
7965                 printf("mkdir failed: %s\n", nt_errstr(status));
7966                 goto out;
7967         }
7968
7969         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
7970                                 NULL, NULL, NULL);
7971         if (!NT_STATUS_IS_OK(status)) {
7972                 printf("cli_qpathinfo2 returned %s\n",
7973                        nt_errstr(status));
7974                 goto out;
7975         }
7976
7977         /* Sleep 3 seconds, then create a file. */
7978         sleep(3);
7979
7980         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
7981                          DENY_NONE, &fnum);
7982         if (!NT_STATUS_IS_OK(status)) {
7983                 printf("cli_openx failed: %s\n", nt_errstr(status));
7984                 goto out;
7985         }
7986
7987         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
7988                                 NULL, NULL, NULL);
7989         if (!NT_STATUS_IS_OK(status)) {
7990                 printf("cli_qpathinfo2 (2) returned %s\n",
7991                        nt_errstr(status));
7992                 goto out;
7993         }
7994
7995         if (timespec_compare(&create_time1, &create_time)) {
7996                 printf("run_dir_createtime: create time was updated (error)\n");
7997         } else {
7998                 printf("run_dir_createtime: create time was not updated (correct)\n");
7999                 ret = true;
8000         }
8001
8002   out:
8003
8004         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8005         cli_rmdir(cli, dname);
8006         if (!torture_close_connection(cli)) {
8007                 ret = false;
8008         }
8009         return ret;
8010 }
8011
8012
8013 static bool run_streamerror(int dummy)
8014 {
8015         struct cli_state *cli;
8016         const char *dname = "\\testdir";
8017         const char *streamname =
8018                 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
8019         NTSTATUS status;
8020         time_t change_time, access_time, write_time;
8021         off_t size;
8022         uint16_t mode, fnum;
8023         bool ret = true;
8024
8025         if (!torture_open_connection(&cli, 0)) {
8026                 return false;
8027         }
8028
8029         cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8030         cli_rmdir(cli, dname);
8031
8032         status = cli_mkdir(cli, dname);
8033         if (!NT_STATUS_IS_OK(status)) {
8034                 printf("mkdir failed: %s\n", nt_errstr(status));
8035                 return false;
8036         }
8037
8038         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
8039                                 &write_time, &size, &mode);
8040         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
8041                 printf("pathinfo returned %s, expected "
8042                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
8043                        nt_errstr(status));
8044                 ret = false;
8045         }
8046
8047         status = cli_ntcreate(cli, streamname, 0x16,
8048                               FILE_READ_DATA|FILE_READ_EA|
8049                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
8050                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
8051                               FILE_OPEN, 0, 0, &fnum);
8052
8053         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
8054                 printf("ntcreate returned %s, expected "
8055                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
8056                        nt_errstr(status));
8057                 ret = false;
8058         }
8059
8060
8061         cli_rmdir(cli, dname);
8062         return ret;
8063 }
8064
8065 static bool run_local_substitute(int dummy)
8066 {
8067         bool ok = true;
8068
8069         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
8070         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
8071         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
8072         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
8073         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
8074         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
8075         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
8076         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
8077
8078         /* Different captialization rules in sub_basic... */
8079
8080         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
8081                        "blaDOM") == 0);
8082
8083         return ok;
8084 }
8085
8086 static bool run_local_base64(int dummy)
8087 {
8088         int i;
8089         bool ret = true;
8090
8091         for (i=1; i<2000; i++) {
8092                 DATA_BLOB blob1, blob2;
8093                 char *b64;
8094
8095                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
8096                 blob1.length = i;
8097                 generate_random_buffer(blob1.data, blob1.length);
8098
8099                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
8100                 if (b64 == NULL) {
8101                         d_fprintf(stderr, "base64_encode_data_blob failed "
8102                                   "for %d bytes\n", i);
8103                         ret = false;
8104                 }
8105                 blob2 = base64_decode_data_blob(b64);
8106                 TALLOC_FREE(b64);
8107
8108                 if (data_blob_cmp(&blob1, &blob2)) {
8109                         d_fprintf(stderr, "data_blob_cmp failed for %d "
8110                                   "bytes\n", i);
8111                         ret = false;
8112                 }
8113                 TALLOC_FREE(blob1.data);
8114                 data_blob_free(&blob2);
8115         }
8116         return ret;
8117 }
8118
8119 static bool run_local_gencache(int dummy)
8120 {
8121         char *val;
8122         time_t tm;
8123         DATA_BLOB blob;
8124         char v;
8125
8126         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
8127                 d_printf("%s: gencache_set() failed\n", __location__);
8128                 return False;
8129         }
8130
8131         if (!gencache_get("foo", NULL, NULL, NULL)) {
8132                 d_printf("%s: gencache_get() failed\n", __location__);
8133                 return False;
8134         }
8135
8136         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
8137                 d_printf("%s: gencache_get() failed\n", __location__);
8138                 return False;
8139         }
8140
8141         if (strcmp(val, "bar") != 0) {
8142                 d_printf("%s: gencache_get() returned %s, expected %s\n",
8143                          __location__, val, "bar");
8144                 TALLOC_FREE(val);
8145                 return False;
8146         }
8147
8148         TALLOC_FREE(val);
8149
8150         if (!gencache_del("foo")) {
8151                 d_printf("%s: gencache_del() failed\n", __location__);
8152                 return False;
8153         }
8154         if (gencache_del("foo")) {
8155                 d_printf("%s: second gencache_del() succeeded\n",
8156                          __location__);
8157                 return False;
8158         }
8159
8160         if (gencache_get("foo", talloc_tos(), &val, &tm)) {
8161                 d_printf("%s: gencache_get() on deleted entry "
8162                          "succeeded\n", __location__);
8163                 return False;
8164         }
8165
8166         blob = data_blob_string_const_null("bar");
8167         tm = time(NULL) + 60;
8168
8169         if (!gencache_set_data_blob("foo", &blob, tm)) {
8170                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
8171                 return False;
8172         }
8173
8174         if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
8175                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
8176                 return False;
8177         }
8178
8179         if (strcmp((const char *)blob.data, "bar") != 0) {
8180                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
8181                          __location__, (const char *)blob.data, "bar");
8182                 data_blob_free(&blob);
8183                 return False;
8184         }
8185
8186         data_blob_free(&blob);
8187
8188         if (!gencache_del("foo")) {
8189                 d_printf("%s: gencache_del() failed\n", __location__);
8190                 return False;
8191         }
8192         if (gencache_del("foo")) {
8193                 d_printf("%s: second gencache_del() succeeded\n",
8194                          __location__);
8195                 return False;
8196         }
8197
8198         if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
8199                 d_printf("%s: gencache_get_data_blob() on deleted entry "
8200                          "succeeded\n", __location__);
8201                 return False;
8202         }
8203
8204         v = 1;
8205         blob.data = (uint8_t *)&v;
8206         blob.length = sizeof(v);
8207
8208         if (!gencache_set_data_blob("blob", &blob, tm)) {
8209                 d_printf("%s: gencache_set_data_blob() failed\n",
8210                          __location__);
8211                 return false;
8212         }
8213         if (gencache_get("blob", talloc_tos(), &val, &tm)) {
8214                 d_printf("%s: gencache_get succeeded\n", __location__);
8215                 return false;
8216         }
8217
8218         return True;
8219 }
8220
8221 static bool rbt_testval(struct db_context *db, const char *key,
8222                         const char *value)
8223 {
8224         struct db_record *rec;
8225         TDB_DATA data = string_tdb_data(value);
8226         bool ret = false;
8227         NTSTATUS status;
8228         TDB_DATA dbvalue;
8229
8230         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
8231         if (rec == NULL) {
8232                 d_fprintf(stderr, "fetch_locked failed\n");
8233                 goto done;
8234         }
8235         status = dbwrap_record_store(rec, data, 0);
8236         if (!NT_STATUS_IS_OK(status)) {
8237                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
8238                 goto done;
8239         }
8240         TALLOC_FREE(rec);
8241
8242         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
8243         if (rec == NULL) {
8244                 d_fprintf(stderr, "second fetch_locked failed\n");
8245                 goto done;
8246         }
8247
8248         dbvalue = dbwrap_record_get_value(rec);
8249         if ((dbvalue.dsize != data.dsize)
8250             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
8251                 d_fprintf(stderr, "Got wrong data back\n");
8252                 goto done;
8253         }
8254
8255         ret = true;
8256  done:
8257         TALLOC_FREE(rec);
8258         return ret;
8259 }
8260
8261 static bool run_local_rbtree(int dummy)
8262 {
8263         struct db_context *db;
8264         bool ret = false;
8265         int i;
8266
8267         db = db_open_rbt(NULL);
8268
8269         if (db == NULL) {
8270                 d_fprintf(stderr, "db_open_rbt failed\n");
8271                 return false;
8272         }
8273
8274         for (i=0; i<1000; i++) {
8275                 char *key, *value;
8276
8277                 if (asprintf(&key, "key%ld", random()) == -1) {
8278                         goto done;
8279                 }
8280                 if (asprintf(&value, "value%ld", random()) == -1) {
8281                         SAFE_FREE(key);
8282                         goto done;
8283                 }
8284
8285                 if (!rbt_testval(db, key, value)) {
8286                         SAFE_FREE(key);
8287                         SAFE_FREE(value);
8288                         goto done;
8289                 }
8290
8291                 SAFE_FREE(value);
8292                 if (asprintf(&value, "value%ld", random()) == -1) {
8293                         SAFE_FREE(key);
8294                         goto done;
8295                 }
8296
8297                 if (!rbt_testval(db, key, value)) {
8298                         SAFE_FREE(key);
8299                         SAFE_FREE(value);
8300                         goto done;
8301                 }
8302
8303                 SAFE_FREE(key);
8304                 SAFE_FREE(value);
8305         }
8306
8307         ret = true;
8308
8309  done:
8310         TALLOC_FREE(db);
8311         return ret;
8312 }
8313
8314
8315 /*
8316   local test for character set functions
8317
8318   This is a very simple test for the functionality in convert_string_error()
8319  */
8320 static bool run_local_convert_string(int dummy)
8321 {
8322         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
8323         const char *test_strings[2] = { "March", "M\303\244rz" };
8324         char dst[7];
8325         int i;
8326
8327         for (i=0; i<2; i++) {
8328                 const char *str = test_strings[i];
8329                 int len = strlen(str);
8330                 size_t converted_size;
8331                 bool ret;
8332
8333                 memset(dst, 'X', sizeof(dst));
8334
8335                 /* first try with real source length */
8336                 ret = convert_string_error(CH_UNIX, CH_UTF8,
8337                                            str, len,
8338                                            dst, sizeof(dst),
8339                                            &converted_size);
8340                 if (ret != true) {
8341                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
8342                         goto failed;
8343                 }
8344
8345                 if (converted_size != len) {
8346                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
8347                                   str, len, (int)converted_size);
8348                         goto failed;
8349                 }
8350
8351                 if (strncmp(str, dst, converted_size) != 0) {
8352                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
8353                         goto failed;
8354                 }
8355
8356                 if (strlen(str) != converted_size) {
8357                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
8358                                   (int)strlen(str), (int)converted_size);
8359                         goto failed;
8360                 }
8361
8362                 if (dst[converted_size] != 'X') {
8363                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
8364                         goto failed;
8365                 }
8366
8367                 /* now with srclen==-1, this causes the nul to be
8368                  * converted too */
8369                 ret = convert_string_error(CH_UNIX, CH_UTF8,
8370                                            str, -1,
8371                                            dst, sizeof(dst),
8372                                            &converted_size);
8373                 if (ret != true) {
8374                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
8375                         goto failed;
8376                 }
8377
8378                 if (converted_size != len+1) {
8379                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
8380                                   str, len, (int)converted_size);
8381                         goto failed;
8382                 }
8383
8384                 if (strncmp(str, dst, converted_size) != 0) {
8385                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
8386                         goto failed;
8387                 }
8388
8389                 if (len+1 != converted_size) {
8390                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
8391                                   len+1, (int)converted_size);
8392                         goto failed;
8393                 }
8394
8395                 if (dst[converted_size] != 'X') {
8396                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
8397                         goto failed;
8398                 }
8399
8400         }
8401
8402
8403         TALLOC_FREE(tmp_ctx);
8404         return true;
8405 failed:
8406         TALLOC_FREE(tmp_ctx);
8407         return false;
8408 }
8409
8410
8411 struct talloc_dict_test {
8412         int content;
8413 };
8414
8415 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
8416 {
8417         int *count = (int *)priv;
8418         *count += 1;
8419         return 0;
8420 }
8421
8422 static bool run_local_talloc_dict(int dummy)
8423 {
8424         struct talloc_dict *dict;
8425         struct talloc_dict_test *t;
8426         int key, count, res;
8427         bool ok;
8428
8429         dict = talloc_dict_init(talloc_tos());
8430         if (dict == NULL) {
8431                 return false;
8432         }
8433
8434         t = talloc(talloc_tos(), struct talloc_dict_test);
8435         if (t == NULL) {
8436                 return false;
8437         }
8438
8439         key = 1;
8440         t->content = 1;
8441         ok = talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), &t);
8442         if (!ok) {
8443                 return false;
8444         }
8445
8446         count = 0;
8447         res = talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count);
8448         if (res == -1) {
8449                 return false;
8450         }
8451
8452         if (count != 1) {
8453                 return false;
8454         }
8455
8456         if (count != res) {
8457                 return false;
8458         }
8459
8460         TALLOC_FREE(dict);
8461
8462         return true;
8463 }
8464
8465 static bool run_local_string_to_sid(int dummy) {
8466         struct dom_sid sid;
8467
8468         if (string_to_sid(&sid, "S--1-5-32-545")) {
8469                 printf("allowing S--1-5-32-545\n");
8470                 return false;
8471         }
8472         if (string_to_sid(&sid, "S-1-5-32-+545")) {
8473                 printf("allowing S-1-5-32-+545\n");
8474                 return false;
8475         }
8476         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")) {
8477                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
8478                 return false;
8479         }
8480         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
8481                 printf("allowing S-1-5-32-545-abc\n");
8482                 return false;
8483         }
8484         if (string_to_sid(&sid, "S-300-5-32-545")) {
8485                 printf("allowing S-300-5-32-545\n");
8486                 return false;
8487         }
8488         if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
8489                 printf("allowing S-1-0xfffffffffffffe-32-545\n");
8490                 return false;
8491         }
8492         if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
8493                 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
8494                 return false;
8495         }
8496         if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
8497                 printf("could not parse S-1-0xfffffffffffe-32-545\n");
8498                 return false;
8499         }
8500         if (!string_to_sid(&sid, "S-1-5-32-545")) {
8501                 printf("could not parse S-1-5-32-545\n");
8502                 return false;
8503         }
8504         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
8505                 printf("mis-parsed S-1-5-32-545 as %s\n",
8506                        sid_string_tos(&sid));
8507                 return false;
8508         }
8509         return true;
8510 }
8511
8512 static bool sid_to_string_test(const char *expected) {
8513         char *str;
8514         bool res = true;
8515         struct dom_sid sid;
8516
8517         if (!string_to_sid(&sid, expected)) {
8518                 printf("could not parse %s\n", expected);
8519                 return false;
8520         }
8521
8522         str = dom_sid_string(NULL, &sid);
8523         if (strcmp(str, expected)) {
8524                 printf("Comparison failed (%s != %s)\n", str, expected);
8525                 res = false;
8526         }
8527         TALLOC_FREE(str);
8528         return res;
8529 }
8530
8531 static bool run_local_sid_to_string(int dummy) {
8532         if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
8533                 return false;
8534         if (!sid_to_string_test("S-1-545"))
8535                 return false;
8536         if (!sid_to_string_test("S-255-3840-1-1-1-1"))
8537                 return false;
8538         return true;
8539 }
8540
8541 static bool run_local_binary_to_sid(int dummy) {
8542         struct dom_sid *sid = talloc(NULL, struct dom_sid);
8543         static const char good_binary_sid[] = {
8544                 0x1, /* revision number */
8545                 15, /* num auths */
8546                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8547                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8548                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8549                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8550                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8551                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8552                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8553                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8554                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8555                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8556                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8557                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8558                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8559                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8560                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8561                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8562         };
8563
8564         static const char long_binary_sid[] = {
8565                 0x1, /* revision number */
8566                 15, /* num auths */
8567                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8568                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8569                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8570                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8571                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8572                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8573                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8574                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8575                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8576                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8577                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8578                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8579                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8580                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8581                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8582                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8583                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8584                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8585                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8586         };
8587
8588         static const char long_binary_sid2[] = {
8589                 0x1, /* revision number */
8590                 32, /* num auths */
8591                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8592                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8593                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8594                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8595                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8596                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8597                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8598                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8599                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8600                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8601                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8602                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8603                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8604                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8605                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8606                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8607                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8608                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8609                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8610                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
8611                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
8612                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
8613                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
8614                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
8615                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
8616                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
8617                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
8618                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
8619                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
8620                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
8621                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
8622                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
8623                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
8624         };
8625
8626         if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
8627                 return false;
8628         }
8629         if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
8630                 return false;
8631         }
8632         if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
8633                 return false;
8634         }
8635         return true;
8636 }
8637
8638 /* Split a path name into filename and stream name components. Canonicalise
8639  * such that an implicit $DATA token is always explicit.
8640  *
8641  * The "specification" of this function can be found in the
8642  * run_local_stream_name() function in torture.c, I've tried those
8643  * combinations against a W2k3 server.
8644  */
8645
8646 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
8647                                        char **pbase, char **pstream)
8648 {
8649         char *base = NULL;
8650         char *stream = NULL;
8651         char *sname; /* stream name */
8652         const char *stype; /* stream type */
8653
8654         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
8655
8656         sname = strchr_m(fname, ':');
8657
8658         if (lp_posix_pathnames() || (sname == NULL)) {
8659                 if (pbase != NULL) {
8660                         base = talloc_strdup(mem_ctx, fname);
8661                         NT_STATUS_HAVE_NO_MEMORY(base);
8662                 }
8663                 goto done;
8664         }
8665
8666         if (pbase != NULL) {
8667                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
8668                 NT_STATUS_HAVE_NO_MEMORY(base);
8669         }
8670
8671         sname += 1;
8672
8673         stype = strchr_m(sname, ':');
8674
8675         if (stype == NULL) {
8676                 sname = talloc_strdup(mem_ctx, sname);
8677                 stype = "$DATA";
8678         }
8679         else {
8680                 if (strcasecmp_m(stype, ":$DATA") != 0) {
8681                         /*
8682                          * If there is an explicit stream type, so far we only
8683                          * allow $DATA. Is there anything else allowed? -- vl
8684                          */
8685                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
8686                         TALLOC_FREE(base);
8687                         return NT_STATUS_OBJECT_NAME_INVALID;
8688                 }
8689                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
8690                 stype += 1;
8691         }
8692
8693         if (sname == NULL) {
8694                 TALLOC_FREE(base);
8695                 return NT_STATUS_NO_MEMORY;
8696         }
8697
8698         if (sname[0] == '\0') {
8699                 /*
8700                  * no stream name, so no stream
8701                  */
8702                 goto done;
8703         }
8704
8705         if (pstream != NULL) {
8706                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
8707                 if (stream == NULL) {
8708                         TALLOC_FREE(sname);
8709                         TALLOC_FREE(base);
8710                         return NT_STATUS_NO_MEMORY;
8711                 }
8712                 /*
8713                  * upper-case the type field
8714                  */
8715                 (void)strupper_m(strchr_m(stream, ':')+1);
8716         }
8717
8718  done:
8719         if (pbase != NULL) {
8720                 *pbase = base;
8721         }
8722         if (pstream != NULL) {
8723                 *pstream = stream;
8724         }
8725         return NT_STATUS_OK;
8726 }
8727
8728 static bool test_stream_name(const char *fname, const char *expected_base,
8729                              const char *expected_stream,
8730                              NTSTATUS expected_status)
8731 {
8732         NTSTATUS status;
8733         char *base = NULL;
8734         char *stream = NULL;
8735
8736         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
8737         if (!NT_STATUS_EQUAL(status, expected_status)) {
8738                 goto error;
8739         }
8740
8741         if (!NT_STATUS_IS_OK(status)) {
8742                 return true;
8743         }
8744
8745         if (base == NULL) goto error;
8746
8747         if (strcmp(expected_base, base) != 0) goto error;
8748
8749         if ((expected_stream != NULL) && (stream == NULL)) goto error;
8750         if ((expected_stream == NULL) && (stream != NULL)) goto error;
8751
8752         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
8753                 goto error;
8754
8755         TALLOC_FREE(base);
8756         TALLOC_FREE(stream);
8757         return true;
8758
8759  error:
8760         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
8761                   fname, expected_base ? expected_base : "<NULL>",
8762                   expected_stream ? expected_stream : "<NULL>",
8763                   nt_errstr(expected_status));
8764         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
8765                   base ? base : "<NULL>", stream ? stream : "<NULL>",
8766                   nt_errstr(status));
8767         TALLOC_FREE(base);
8768         TALLOC_FREE(stream);
8769         return false;
8770 }
8771
8772 static bool run_local_stream_name(int dummy)
8773 {
8774         bool ret = true;
8775
8776         ret &= test_stream_name(
8777                 "bla", "bla", NULL, NT_STATUS_OK);
8778         ret &= test_stream_name(
8779                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
8780         ret &= test_stream_name(
8781                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8782         ret &= test_stream_name(
8783                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
8784         ret &= test_stream_name(
8785                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8786         ret &= test_stream_name(
8787                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
8788         ret &= test_stream_name(
8789                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
8790         ret &= test_stream_name(
8791                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
8792
8793         return ret;
8794 }
8795
8796 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
8797 {
8798         if (a.length != b.length) {
8799                 printf("a.length=%d != b.length=%d\n",
8800                        (int)a.length, (int)b.length);
8801                 return false;
8802         }
8803         if (memcmp(a.data, b.data, a.length) != 0) {
8804                 printf("a.data and b.data differ\n");
8805                 return false;
8806         }
8807         return true;
8808 }
8809
8810 static bool run_local_memcache(int dummy)
8811 {
8812         struct memcache *cache;
8813         DATA_BLOB k1, k2;
8814         DATA_BLOB d1, d2, d3;
8815         DATA_BLOB v1, v2, v3;
8816
8817         TALLOC_CTX *mem_ctx;
8818         char *str1, *str2;
8819         size_t size1, size2;
8820         bool ret = false;
8821
8822         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
8823
8824         if (cache == NULL) {
8825                 printf("memcache_init failed\n");
8826                 return false;
8827         }
8828
8829         d1 = data_blob_const("d1", 2);
8830         d2 = data_blob_const("d2", 2);
8831         d3 = data_blob_const("d3", 2);
8832
8833         k1 = data_blob_const("d1", 2);
8834         k2 = data_blob_const("d2", 2);
8835
8836         memcache_add(cache, STAT_CACHE, k1, d1);
8837         memcache_add(cache, GETWD_CACHE, k2, d2);
8838
8839         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
8840                 printf("could not find k1\n");
8841                 return false;
8842         }
8843         if (!data_blob_equal(d1, v1)) {
8844                 return false;
8845         }
8846
8847         if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8848                 printf("could not find k2\n");
8849                 return false;
8850         }
8851         if (!data_blob_equal(d2, v2)) {
8852                 return false;
8853         }
8854
8855         memcache_add(cache, STAT_CACHE, k1, d3);
8856
8857         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
8858                 printf("could not find replaced k1\n");
8859                 return false;
8860         }
8861         if (!data_blob_equal(d3, v3)) {
8862                 return false;
8863         }
8864
8865         memcache_add(cache, GETWD_CACHE, k1, d1);
8866
8867         if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8868                 printf("Did find k2, should have been purged\n");
8869                 return false;
8870         }
8871
8872         TALLOC_FREE(cache);
8873
8874         cache = memcache_init(NULL, 0);
8875
8876         mem_ctx = talloc_init("foo");
8877
8878         str1 = talloc_strdup(mem_ctx, "string1");
8879         str2 = talloc_strdup(mem_ctx, "string2");
8880
8881         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8882                             data_blob_string_const("torture"), &str1);
8883         size1 = talloc_total_size(cache);
8884
8885         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8886                             data_blob_string_const("torture"), &str2);
8887         size2 = talloc_total_size(cache);
8888
8889         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
8890
8891         if (size2 > size1) {
8892                 printf("memcache leaks memory!\n");
8893                 goto fail;
8894         }
8895
8896         ret = true;
8897  fail:
8898         TALLOC_FREE(cache);
8899         return ret;
8900 }
8901
8902 static void wbclient_done(struct tevent_req *req)
8903 {
8904         wbcErr wbc_err;
8905         struct winbindd_response *wb_resp;
8906         int *i = (int *)tevent_req_callback_data_void(req);
8907
8908         wbc_err = wb_trans_recv(req, req, &wb_resp);
8909         TALLOC_FREE(req);
8910         *i += 1;
8911         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
8912 }
8913
8914 static bool run_local_wbclient(int dummy)
8915 {
8916         struct tevent_context *ev;
8917         struct wb_context **wb_ctx;
8918         struct winbindd_request wb_req;
8919         bool result = false;
8920         int i, j;
8921
8922         BlockSignals(True, SIGPIPE);
8923
8924         ev = tevent_context_init(talloc_tos());
8925         if (ev == NULL) {
8926                 goto fail;
8927         }
8928
8929         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
8930         if (wb_ctx == NULL) {
8931                 goto fail;
8932         }
8933
8934         ZERO_STRUCT(wb_req);
8935         wb_req.cmd = WINBINDD_PING;
8936
8937         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
8938
8939         for (i=0; i<torture_nprocs; i++) {
8940                 wb_ctx[i] = wb_context_init(ev, NULL);
8941                 if (wb_ctx[i] == NULL) {
8942                         goto fail;
8943                 }
8944                 for (j=0; j<torture_numops; j++) {
8945                         struct tevent_req *req;
8946                         req = wb_trans_send(ev, ev, wb_ctx[i],
8947                                             (j % 2) == 0, &wb_req);
8948                         if (req == NULL) {
8949                                 goto fail;
8950                         }
8951                         tevent_req_set_callback(req, wbclient_done, &i);
8952                 }
8953         }
8954
8955         i = 0;
8956
8957         while (i < torture_nprocs * torture_numops) {
8958                 tevent_loop_once(ev);
8959         }
8960
8961         result = true;
8962  fail:
8963         TALLOC_FREE(ev);
8964         return result;
8965 }
8966
8967 static void getaddrinfo_finished(struct tevent_req *req)
8968 {
8969         char *name = (char *)tevent_req_callback_data_void(req);
8970         struct addrinfo *ainfo;
8971         int res;
8972
8973         res = getaddrinfo_recv(req, &ainfo);
8974         if (res != 0) {
8975                 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
8976                 return;
8977         }
8978         d_printf("gai(%s) succeeded\n", name);
8979         freeaddrinfo(ainfo);
8980 }
8981
8982 static bool run_getaddrinfo_send(int dummy)
8983 {
8984         TALLOC_CTX *frame = talloc_stackframe();
8985         struct fncall_context *ctx;
8986         struct tevent_context *ev;
8987         bool result = false;
8988         const char *names[4] = { "www.samba.org", "notfound.samba.org",
8989                                  "www.slashdot.org", "heise.de" };
8990         struct tevent_req *reqs[4];
8991         int i;
8992
8993         ev = samba_tevent_context_init(frame);
8994         if (ev == NULL) {
8995                 goto fail;
8996         }
8997
8998         ctx = fncall_context_init(frame, 4);
8999
9000         for (i=0; i<ARRAY_SIZE(names); i++) {
9001                 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
9002                                            NULL);
9003                 if (reqs[i] == NULL) {
9004                         goto fail;
9005                 }
9006                 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
9007                                         discard_const_p(void, names[i]));
9008         }
9009
9010         for (i=0; i<ARRAY_SIZE(reqs); i++) {
9011                 tevent_loop_once(ev);
9012         }
9013
9014         result = true;
9015 fail:
9016         TALLOC_FREE(frame);
9017         return result;
9018 }
9019
9020 static bool dbtrans_inc(struct db_context *db)
9021 {
9022         struct db_record *rec;
9023         uint32_t val;
9024         bool ret = false;
9025         NTSTATUS status;
9026         TDB_DATA value;
9027
9028         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
9029         if (rec == NULL) {
9030                 printf(__location__ "fetch_lock failed\n");
9031                 return false;
9032         }
9033
9034         value = dbwrap_record_get_value(rec);
9035
9036         if (value.dsize != sizeof(uint32_t)) {
9037                 printf(__location__ "value.dsize = %d\n",
9038                        (int)value.dsize);
9039                 goto fail;
9040         }
9041
9042         memcpy(&val, value.dptr, sizeof(val));
9043         val += 1;
9044
9045         status = dbwrap_record_store(
9046                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
9047         if (!NT_STATUS_IS_OK(status)) {
9048                 printf(__location__ "store failed: %s\n",
9049                        nt_errstr(status));
9050                 goto fail;
9051         }
9052
9053         ret = true;
9054 fail:
9055         TALLOC_FREE(rec);
9056         return ret;
9057 }
9058
9059 static bool run_local_dbtrans(int dummy)
9060 {
9061         struct db_context *db;
9062         struct db_record *rec;
9063         NTSTATUS status;
9064         uint32_t initial;
9065         int res;
9066         TDB_DATA value;
9067
9068         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
9069                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
9070                      DBWRAP_FLAG_NONE);
9071         if (db == NULL) {
9072                 printf("Could not open transtest.db\n");
9073                 return false;
9074         }
9075
9076         res = dbwrap_transaction_start(db);
9077         if (res != 0) {
9078                 printf(__location__ "transaction_start failed\n");
9079                 return false;
9080         }
9081
9082         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
9083         if (rec == NULL) {
9084                 printf(__location__ "fetch_lock failed\n");
9085                 return false;
9086         }
9087
9088         value = dbwrap_record_get_value(rec);
9089
9090         if (value.dptr == NULL) {
9091                 initial = 0;
9092                 status = dbwrap_record_store(
9093                         rec, make_tdb_data((uint8_t *)&initial,
9094                                            sizeof(initial)),
9095                         0);
9096                 if (!NT_STATUS_IS_OK(status)) {
9097                         printf(__location__ "store returned %s\n",
9098                                nt_errstr(status));
9099                         return false;
9100                 }
9101         }
9102
9103         TALLOC_FREE(rec);
9104
9105         res = dbwrap_transaction_commit(db);
9106         if (res != 0) {
9107                 printf(__location__ "transaction_commit failed\n");
9108                 return false;
9109         }
9110
9111         while (true) {
9112                 uint32_t val, val2;
9113                 int i;
9114
9115                 res = dbwrap_transaction_start(db);
9116                 if (res != 0) {
9117                         printf(__location__ "transaction_start failed\n");
9118                         break;
9119                 }
9120
9121                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
9122                 if (!NT_STATUS_IS_OK(status)) {
9123                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
9124                                nt_errstr(status));
9125                         break;
9126                 }
9127
9128                 for (i=0; i<10; i++) {
9129                         if (!dbtrans_inc(db)) {
9130                                 return false;
9131                         }
9132                 }
9133
9134                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
9135                 if (!NT_STATUS_IS_OK(status)) {
9136                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
9137                                nt_errstr(status));
9138                         break;
9139                 }
9140
9141                 if (val2 != val + 10) {
9142                         printf(__location__ "val=%d, val2=%d\n",
9143                                (int)val, (int)val2);
9144                         break;
9145                 }
9146
9147                 printf("val2=%d\r", val2);
9148
9149                 res = dbwrap_transaction_commit(db);
9150                 if (res != 0) {
9151                         printf(__location__ "transaction_commit failed\n");
9152                         break;
9153                 }
9154         }
9155
9156         TALLOC_FREE(db);
9157         return true;
9158 }
9159
9160 /*
9161  * Just a dummy test to be run under a debugger. There's no real way
9162  * to inspect the tevent_select specific function from outside of
9163  * tevent_select.c.
9164  */
9165
9166 static bool run_local_tevent_select(int dummy)
9167 {
9168         struct tevent_context *ev;
9169         struct tevent_fd *fd1, *fd2;
9170         bool result = false;
9171
9172         ev = tevent_context_init_byname(NULL, "select");
9173         if (ev == NULL) {
9174                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
9175                 goto fail;
9176         }
9177
9178         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
9179         if (fd1 == NULL) {
9180                 d_fprintf(stderr, "tevent_add_fd failed\n");
9181                 goto fail;
9182         }
9183         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
9184         if (fd2 == NULL) {
9185                 d_fprintf(stderr, "tevent_add_fd failed\n");
9186                 goto fail;
9187         }
9188         TALLOC_FREE(fd2);
9189
9190         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
9191         if (fd2 == NULL) {
9192                 d_fprintf(stderr, "tevent_add_fd failed\n");
9193                 goto fail;
9194         }
9195
9196         result = true;
9197 fail:
9198         TALLOC_FREE(ev);
9199         return result;
9200 }
9201
9202 static bool run_local_hex_encode_buf(int dummy)
9203 {
9204         char buf[17];
9205         uint8_t src[8];
9206         int i;
9207
9208         for (i=0; i<sizeof(src); i++) {
9209                 src[i] = i;
9210         }
9211         hex_encode_buf(buf, src, sizeof(src));
9212         if (strcmp(buf, "0001020304050607") != 0) {
9213                 return false;
9214         }
9215         hex_encode_buf(buf, NULL, 0);
9216         if (buf[0] != '\0') {
9217                 return false;
9218         }
9219         return true;
9220 }
9221
9222 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
9223         "0.0.0.0",
9224         "::0",
9225         "1.2.3.1",
9226         "0.0.0.0",
9227         "0.0.0.0",
9228         "1.2.3.2",
9229         "1.2.3.3",
9230         "1.2.3.4",
9231         "1.2.3.5",
9232         "::0",
9233         "1.2.3.6",
9234         "1.2.3.7",
9235         "::0",
9236         "::0",
9237         "::0",
9238         "1.2.3.8",
9239         "1.2.3.9",
9240         "1.2.3.10",
9241         "1.2.3.11",
9242         "1.2.3.12",
9243         "1.2.3.13",
9244         "1001:1111:1111:1000:0:1111:1111:1111",
9245         "1.2.3.1",
9246         "1.2.3.2",
9247         "1.2.3.3",
9248         "1.2.3.12",
9249         "::0",
9250         "::0"
9251 };
9252
9253 static const char *remove_duplicate_addrs2_test_strings_result[] = {
9254         "1.2.3.1",
9255         "1.2.3.2",
9256         "1.2.3.3",
9257         "1.2.3.4",
9258         "1.2.3.5",
9259         "1.2.3.6",
9260         "1.2.3.7",
9261         "1.2.3.8",
9262         "1.2.3.9",
9263         "1.2.3.10",
9264         "1.2.3.11",
9265         "1.2.3.12",
9266         "1.2.3.13",
9267         "1001:1111:1111:1000:0:1111:1111:1111"
9268 };
9269
9270 static bool run_local_remove_duplicate_addrs2(int dummy)
9271 {
9272         struct ip_service test_vector[28];
9273         int count, i;
9274
9275         /* Construct the sockaddr_storage test vector. */
9276         for (i = 0; i < 28; i++) {
9277                 struct addrinfo hints;
9278                 struct addrinfo *res = NULL;
9279                 int ret;
9280
9281                 memset(&hints, '\0', sizeof(hints));
9282                 hints.ai_flags = AI_NUMERICHOST;
9283                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
9284                                 NULL,
9285                                 &hints,
9286                                 &res);
9287                 if (ret) {
9288                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
9289                                 remove_duplicate_addrs2_test_strings_vector[i]);
9290                         return false;
9291                 }
9292                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
9293                 memcpy(&test_vector[i].ss,
9294                         res->ai_addr,
9295                         res->ai_addrlen);
9296                 freeaddrinfo(res);
9297         }
9298
9299         count = remove_duplicate_addrs2(test_vector, i);
9300
9301         if (count != 14) {
9302                 fprintf(stderr, "count wrong (%d) should be 14\n",
9303                         count);
9304                 return false;
9305         }
9306
9307         for (i = 0; i < count; i++) {
9308                 char addr[INET6_ADDRSTRLEN];
9309
9310                 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
9311
9312                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
9313                         fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
9314                                 i,
9315                                 addr,
9316                                 remove_duplicate_addrs2_test_strings_result[i]);
9317                         return false;
9318                 }
9319         }
9320
9321         printf("run_local_remove_duplicate_addrs2: success\n");
9322         return true;
9323 }
9324
9325 static bool run_local_tdb_opener(int dummy)
9326 {
9327         TDB_CONTEXT *t;
9328         unsigned v = 0;
9329
9330         while (1) {
9331                 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
9332                              O_RDWR|O_CREAT, 0755);
9333                 if (t == NULL) {
9334                         perror("tdb_open failed");
9335                         return false;
9336                 }
9337                 tdb_close(t);
9338
9339                 v += 1;
9340                 printf("\r%u", v);
9341         }
9342         return true;
9343 }
9344
9345 static bool run_local_tdb_writer(int dummy)
9346 {
9347         TDB_CONTEXT *t;
9348         unsigned v = 0;
9349         TDB_DATA val;
9350
9351         t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
9352         if (t == 0) {
9353                 perror("tdb_open failed");
9354                 return 1;
9355         }
9356
9357         val.dptr = (uint8_t *)&v;
9358         val.dsize = sizeof(v);
9359
9360         while (1) {
9361                 TDB_DATA data;
9362                 int ret;
9363
9364                 ret = tdb_store(t, val, val, 0);
9365                 if (ret != 0) {
9366                         printf("%s\n", tdb_errorstr(t));
9367                 }
9368                 v += 1;
9369                 printf("\r%u", v);
9370
9371                 data = tdb_fetch(t, val);
9372                 if (data.dptr != NULL) {
9373                         SAFE_FREE(data.dptr);
9374                 }
9375         }
9376         return true;
9377 }
9378
9379 static double create_procs(bool (*fn)(int), bool *result)
9380 {
9381         int i, status;
9382         volatile pid_t *child_status;
9383         volatile bool *child_status_out;
9384         int synccount;
9385         int tries = 8;
9386         struct timeval start;
9387
9388         synccount = 0;
9389
9390         child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
9391         if (!child_status) {
9392                 printf("Failed to setup shared memory\n");
9393                 return -1;
9394         }
9395
9396         child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
9397         if (!child_status_out) {
9398                 printf("Failed to setup result status shared memory\n");
9399                 return -1;
9400         }
9401
9402         for (i = 0; i < torture_nprocs; i++) {
9403                 child_status[i] = 0;
9404                 child_status_out[i] = True;
9405         }
9406
9407         start = timeval_current();
9408
9409         for (i=0;i<torture_nprocs;i++) {
9410                 procnum = i;
9411                 if (fork() == 0) {
9412                         pid_t mypid = getpid();
9413                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
9414
9415                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
9416
9417                         while (1) {
9418                                 if (torture_open_connection(&current_cli, i)) break;
9419                                 if (tries-- == 0) {
9420                                         printf("pid %d failed to start\n", (int)getpid());
9421                                         _exit(1);
9422                                 }
9423                                 smb_msleep(10); 
9424                         }
9425
9426                         child_status[i] = getpid();
9427
9428                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
9429
9430                         child_status_out[i] = fn(i);
9431                         _exit(0);
9432                 }
9433         }
9434
9435         do {
9436                 synccount = 0;
9437                 for (i=0;i<torture_nprocs;i++) {
9438                         if (child_status[i]) synccount++;
9439                 }
9440                 if (synccount == torture_nprocs) break;
9441                 smb_msleep(10);
9442         } while (timeval_elapsed(&start) < 30);
9443
9444         if (synccount != torture_nprocs) {
9445                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
9446                 *result = False;
9447                 return timeval_elapsed(&start);
9448         }
9449
9450         /* start the client load */
9451         start = timeval_current();
9452
9453         for (i=0;i<torture_nprocs;i++) {
9454                 child_status[i] = 0;
9455         }
9456
9457         printf("%d clients started\n", torture_nprocs);
9458
9459         for (i=0;i<torture_nprocs;i++) {
9460                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
9461         }
9462
9463         printf("\n");
9464
9465         for (i=0;i<torture_nprocs;i++) {
9466                 if (!child_status_out[i]) {
9467                         *result = False;
9468                 }
9469         }
9470         return timeval_elapsed(&start);
9471 }
9472
9473 #define FLAG_MULTIPROC 1
9474
9475 static struct {
9476         const char *name;
9477         bool (*fn)(int);
9478         unsigned flags;
9479 } torture_ops[] = {
9480         {"FDPASS", run_fdpasstest, 0},
9481         {"LOCK1",  run_locktest1,  0},
9482         {"LOCK2",  run_locktest2,  0},
9483         {"LOCK3",  run_locktest3,  0},
9484         {"LOCK4",  run_locktest4,  0},
9485         {"LOCK5",  run_locktest5,  0},
9486         {"LOCK6",  run_locktest6,  0},
9487         {"LOCK7",  run_locktest7,  0},
9488         {"LOCK8",  run_locktest8,  0},
9489         {"LOCK9",  run_locktest9,  0},
9490         {"UNLINK", run_unlinktest, 0},
9491         {"BROWSE", run_browsetest, 0},
9492         {"ATTR",   run_attrtest,   0},
9493         {"TRANS2", run_trans2test, 0},
9494         {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
9495         {"TORTURE",run_torture,    FLAG_MULTIPROC},
9496         {"RANDOMIPC", run_randomipc, 0},
9497         {"NEGNOWAIT", run_negprot_nowait, 0},
9498         {"NBENCH",  run_nbench, 0},
9499         {"NBENCH2", run_nbench2, 0},
9500         {"OPLOCK1",  run_oplock1, 0},
9501         {"OPLOCK2",  run_oplock2, 0},
9502         {"OPLOCK4",  run_oplock4, 0},
9503         {"DIR",  run_dirtest, 0},
9504         {"DIR1",  run_dirtest1, 0},
9505         {"DIR-CREATETIME",  run_dir_createtime, 0},
9506         {"DENY1",  torture_denytest1, 0},
9507         {"DENY2",  torture_denytest2, 0},
9508         {"TCON",  run_tcon_test, 0},
9509         {"TCONDEV",  run_tcon_devtype_test, 0},
9510         {"RW1",  run_readwritetest, 0},
9511         {"RW2",  run_readwritemulti, FLAG_MULTIPROC},
9512         {"RW3",  run_readwritelarge, 0},
9513         {"RW-SIGNING",  run_readwritelarge_signtest, 0},
9514         {"OPEN", run_opentest, 0},
9515         {"POSIX", run_simple_posix_open_test, 0},
9516         {"POSIX-APPEND", run_posix_append, 0},
9517         {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
9518         {"ASYNC-ECHO", run_async_echo, 0},
9519         { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
9520         { "SHORTNAME-TEST", run_shortname_test, 0},
9521         { "ADDRCHANGE", run_addrchange, 0},
9522 #if 1
9523         {"OPENATTR", run_openattrtest, 0},
9524 #endif
9525         {"XCOPY", run_xcopy, 0},
9526         {"RENAME", run_rename, 0},
9527         {"DELETE", run_deletetest, 0},
9528         {"DELETE-LN", run_deletetest_ln, 0},
9529         {"PROPERTIES", run_properties, 0},
9530         {"MANGLE", torture_mangle, 0},
9531         {"MANGLE1", run_mangle1, 0},
9532         {"W2K", run_w2ktest, 0},
9533         {"TRANS2SCAN", torture_trans2_scan, 0},
9534         {"NTTRANSSCAN", torture_nttrans_scan, 0},
9535         {"UTABLE", torture_utable, 0},
9536         {"CASETABLE", torture_casetable, 0},
9537         {"ERRMAPEXTRACT", run_error_map_extract, 0},
9538         {"PIPE_NUMBER", run_pipe_number, 0},
9539         {"TCON2",  run_tcon2_test, 0},
9540         {"IOCTL",  torture_ioctl_test, 0},
9541         {"CHKPATH",  torture_chkpath_test, 0},
9542         {"FDSESS", run_fdsesstest, 0},
9543         { "EATEST", run_eatest, 0},
9544         { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
9545         { "CHAIN1", run_chain1, 0},
9546         { "CHAIN2", run_chain2, 0},
9547         { "CHAIN3", run_chain3, 0},
9548         { "WINDOWS-WRITE", run_windows_write, 0},
9549         { "LARGE_READX", run_large_readx, 0},
9550         { "NTTRANS-CREATE", run_nttrans_create, 0},
9551         { "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
9552         { "CLI_ECHO", run_cli_echo, 0},
9553         { "GETADDRINFO", run_getaddrinfo_send, 0},
9554         { "TLDAP", run_tldap },
9555         { "STREAMERROR", run_streamerror },
9556         { "NOTIFY-BENCH", run_notify_bench },
9557         { "NOTIFY-BENCH2", run_notify_bench2 },
9558         { "NOTIFY-BENCH3", run_notify_bench3 },
9559         { "BAD-NBT-SESSION", run_bad_nbt_session },
9560         { "SMB-ANY-CONNECT", run_smb_any_connect },
9561         { "NOTIFY-ONLINE", run_notify_online },
9562         { "SMB2-BASIC", run_smb2_basic },
9563         { "SMB2-NEGPROT", run_smb2_negprot },
9564         { "SMB2-SESSION-RECONNECT", run_smb2_session_reconnect },
9565         { "SMB2-TCON-DEPENDENCE", run_smb2_tcon_dependence },
9566         { "SMB2-MULTI-CHANNEL", run_smb2_multi_channel },
9567         { "SMB2-SESSION-REAUTH", run_smb2_session_reauth },
9568         { "CLEANUP1", run_cleanup1 },
9569         { "CLEANUP2", run_cleanup2 },
9570         { "CLEANUP3", run_cleanup3 },
9571         { "CLEANUP4", run_cleanup4 },
9572         { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
9573         { "LOCAL-GENCACHE", run_local_gencache, 0},
9574         { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
9575         { "LOCAL-CTDB-CONN", run_ctdb_conn, 0},
9576         { "LOCAL-DBWRAP-WATCH1", run_dbwrap_watch1, 0 },
9577         { "LOCAL-MESSAGING-READ1", run_messaging_read1, 0 },
9578         { "LOCAL-MESSAGING-READ2", run_messaging_read2, 0 },
9579         { "LOCAL-MESSAGING-READ3", run_messaging_read3, 0 },
9580         { "LOCAL-BASE64", run_local_base64, 0},
9581         { "LOCAL-RBTREE", run_local_rbtree, 0},
9582         { "LOCAL-MEMCACHE", run_local_memcache, 0},
9583         { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
9584         { "LOCAL-WBCLIENT", run_local_wbclient, 0},
9585         { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
9586         { "LOCAL-sid_to_string", run_local_sid_to_string, 0},
9587         { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
9588         { "LOCAL-DBTRANS", run_local_dbtrans, 0},
9589         { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
9590         { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
9591         { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
9592         { "LOCAL-sprintf_append", run_local_sprintf_append, 0},
9593         { "LOCAL-hex_encode_buf", run_local_hex_encode_buf, 0},
9594         { "LOCAL-IDMAP-TDB-COMMON", run_idmap_tdb_common_test, 0},
9595         { "LOCAL-remove_duplicate_addrs2", run_local_remove_duplicate_addrs2, 0},
9596         { "local-tdb-opener", run_local_tdb_opener, 0 },
9597         { "local-tdb-writer", run_local_tdb_writer, 0 },
9598         { "LOCAL-DBWRAP-CTDB", run_local_dbwrap_ctdb, 0 },
9599         { "LOCAL-BENCH-PTHREADPOOL", run_bench_pthreadpool, 0 },
9600         { "qpathinfo-bufsize", run_qpathinfo_bufsize, 0 },
9601         {NULL, NULL, 0}};
9602
9603 /*
9604  * dummy function to satisfy linker dependency
9605  */
9606 struct tevent_context *winbind_event_context(void);
9607 struct tevent_context *winbind_event_context(void)
9608 {
9609         return NULL;
9610 }
9611
9612 /****************************************************************************
9613 run a specified test or "ALL"
9614 ****************************************************************************/
9615 static bool run_test(const char *name)
9616 {
9617         bool ret = True;
9618         bool result = True;
9619         bool found = False;
9620         int i;
9621         double t;
9622         if (strequal(name,"ALL")) {
9623                 for (i=0;torture_ops[i].name;i++) {
9624                         run_test(torture_ops[i].name);
9625                 }
9626                 found = True;
9627         }
9628
9629         for (i=0;torture_ops[i].name;i++) {
9630                 fstr_sprintf(randomfname, "\\XX%x", 
9631                          (unsigned)random());
9632
9633                 if (strequal(name, torture_ops[i].name)) {
9634                         found = True;
9635                         printf("Running %s\n", name);
9636                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
9637                                 t = create_procs(torture_ops[i].fn, &result);
9638                                 if (!result) { 
9639                                         ret = False;
9640                                         printf("TEST %s FAILED!\n", name);
9641                                 }
9642                         } else {
9643                                 struct timeval start;
9644                                 start = timeval_current();
9645                                 if (!torture_ops[i].fn(0)) {
9646                                         ret = False;
9647                                         printf("TEST %s FAILED!\n", name);
9648                                 }
9649                                 t = timeval_elapsed(&start);
9650                         }
9651                         printf("%s took %g secs\n\n", name, t);
9652                 }
9653         }
9654
9655         if (!found) {
9656                 printf("Did not find a test named %s\n", name);
9657                 ret = False;
9658         }
9659
9660         return ret;
9661 }
9662
9663
9664 static void usage(void)
9665 {
9666         int i;
9667
9668         printf("WARNING samba4 test suite is much more complete nowadays.\n");
9669         printf("Please use samba4 torture.\n\n");
9670
9671         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
9672
9673         printf("\t-d debuglevel\n");
9674         printf("\t-U user%%pass\n");
9675         printf("\t-k               use kerberos\n");
9676         printf("\t-N numprocs\n");
9677         printf("\t-n my_netbios_name\n");
9678         printf("\t-W workgroup\n");
9679         printf("\t-o num_operations\n");
9680         printf("\t-O socket_options\n");
9681         printf("\t-m maximum protocol\n");
9682         printf("\t-L use oplocks\n");
9683         printf("\t-c CLIENT.TXT   specify client load file for NBENCH\n");
9684         printf("\t-A showall\n");
9685         printf("\t-p port\n");
9686         printf("\t-s seed\n");
9687         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
9688         printf("\t-f filename   filename to test\n");
9689         printf("\n\n");
9690
9691         printf("tests are:");
9692         for (i=0;torture_ops[i].name;i++) {
9693                 printf(" %s", torture_ops[i].name);
9694         }
9695         printf("\n");
9696
9697         printf("default test is ALL\n");
9698
9699         exit(1);
9700 }
9701
9702 /****************************************************************************
9703   main program
9704 ****************************************************************************/
9705  int main(int argc,char *argv[])
9706 {
9707         int opt, i;
9708         char *p;
9709         int gotuser = 0;
9710         int gotpass = 0;
9711         bool correct = True;
9712         TALLOC_CTX *frame = talloc_stackframe();
9713         int seed = time(NULL);
9714
9715 #ifdef HAVE_SETBUFFER
9716         setbuffer(stdout, NULL, 0);
9717 #endif
9718
9719         setup_logging("smbtorture", DEBUG_STDOUT);
9720
9721         load_case_tables();
9722         fault_setup();
9723
9724         if (is_default_dyn_CONFIGFILE()) {
9725                 if(getenv("SMB_CONF_PATH")) {
9726                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
9727                 }
9728         }
9729         lp_load_global(get_dyn_CONFIGFILE());
9730         load_interfaces();
9731
9732         if (argc < 2) {
9733                 usage();
9734         }
9735
9736         for(p = argv[1]; *p; p++)
9737           if(*p == '\\')
9738             *p = '/';
9739
9740         if (strncmp(argv[1], "//", 2)) {
9741                 usage();
9742         }
9743
9744         fstrcpy(host, &argv[1][2]);
9745         p = strchr_m(&host[2],'/');
9746         if (!p) {
9747                 usage();
9748         }
9749         *p = 0;
9750         fstrcpy(share, p+1);
9751
9752         fstrcpy(myname, get_myname(talloc_tos()));
9753         if (!*myname) {
9754                 fprintf(stderr, "Failed to get my hostname.\n");
9755                 return 1;
9756         }
9757
9758         if (*username == 0 && getenv("LOGNAME")) {
9759           fstrcpy(username,getenv("LOGNAME"));
9760         }
9761
9762         argc--;
9763         argv++;
9764
9765         fstrcpy(workgroup, lp_workgroup());
9766
9767         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
9768                != EOF) {
9769                 switch (opt) {
9770                 case 'p':
9771                         port_to_use = atoi(optarg);
9772                         break;
9773                 case 's':
9774                         seed = atoi(optarg);
9775                         break;
9776                 case 'W':
9777                         fstrcpy(workgroup,optarg);
9778                         break;
9779                 case 'm':
9780                         lp_set_cmdline("client max protocol", optarg);
9781                         break;
9782                 case 'N':
9783                         torture_nprocs = atoi(optarg);
9784                         break;
9785                 case 'o':
9786                         torture_numops = atoi(optarg);
9787                         break;
9788                 case 'd':
9789                         lp_set_cmdline("log level", optarg);
9790                         break;
9791                 case 'O':
9792                         sockops = optarg;
9793                         break;
9794                 case 'L':
9795                         use_oplocks = True;
9796                         break;
9797                 case 'l':
9798                         local_path = optarg;
9799                         break;
9800                 case 'A':
9801                         torture_showall = True;
9802                         break;
9803                 case 'n':
9804                         fstrcpy(myname, optarg);
9805                         break;
9806                 case 'c':
9807                         client_txt = optarg;
9808                         break;
9809                 case 'e':
9810                         do_encrypt = true;
9811                         break;
9812                 case 'k':
9813 #ifdef HAVE_KRB5
9814                         use_kerberos = True;
9815 #else
9816                         d_printf("No kerberos support compiled in\n");
9817                         exit(1);
9818 #endif
9819                         break;
9820                 case 'U':
9821                         gotuser = 1;
9822                         fstrcpy(username,optarg);
9823                         p = strchr_m(username,'%');
9824                         if (p) {
9825                                 *p = 0;
9826                                 fstrcpy(password, p+1);
9827                                 gotpass = 1;
9828                         }
9829                         break;
9830                 case 'b':
9831                         fstrcpy(multishare_conn_fname, optarg);
9832                         use_multishare_conn = True;
9833                         break;
9834                 case 'B':
9835                         torture_blocksize = atoi(optarg);
9836                         break;
9837                 case 'f':
9838                         test_filename = SMB_STRDUP(optarg);
9839                         break;
9840                 default:
9841                         printf("Unknown option %c (%d)\n", (char)opt, opt);
9842                         usage();
9843                 }
9844         }
9845
9846         d_printf("using seed %d\n", seed);
9847
9848         srandom(seed);
9849
9850         if(use_kerberos && !gotuser) gotpass = True;
9851
9852         while (!gotpass) {
9853                 char pwd[256] = {0};
9854                 int rc;
9855
9856                 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
9857                 if (rc == 0) {
9858                         fstrcpy(password, pwd);
9859                         gotpass = 1;
9860                 }
9861         }
9862
9863         printf("host=%s share=%s user=%s myname=%s\n", 
9864                host, share, username, myname);
9865
9866         if (argc == optind) {
9867                 correct = run_test("ALL");
9868         } else {
9869                 for (i=optind;i<argc;i++) {
9870                         if (!run_test(argv[i])) {
9871                                 correct = False;
9872                         }
9873                 }
9874         }
9875
9876         TALLOC_FREE(frame);
9877
9878         if (correct) {
9879                 return(0);
9880         } else {
9881                 return(1);
9882         }
9883 }