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