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