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