s3:torture:delete: untangle function call from result check
[nivanova/samba-autobuild/.git] / source3 / torture / torture.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-1998
5    Copyright (C) Jeremy Allison 2009
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/shmem.h"
23 #include "wbc_async.h"
24 #include "torture/proto.h"
25 #include "libcli/security/security.h"
26 #include "tldap.h"
27 #include "tldap_util.h"
28 #include "../librpc/gen_ndr/svcctl.h"
29 #include "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 event_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 = event_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 = 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 = 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 = True;
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                 correct = False;
3878                 goto fail;
3879         }
3880
3881         status = cli_close(cli1, fnum1);
3882         if (!NT_STATUS_IS_OK(status)) {
3883                 printf("[1] close failed (%s)\n", nt_errstr(status));
3884                 correct = False;
3885                 goto fail;
3886         }
3887
3888         if (NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1))) {
3889                 printf("[1] open of %s succeeded (should fail)\n", fname);
3890                 correct = False;
3891                 goto fail;
3892         }
3893
3894         printf("first delete on close test succeeded.\n");
3895
3896         /* Test 2 - this should delete the file on close. */
3897
3898         cli_setatr(cli1, fname, 0, 0);
3899         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3900
3901         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3902                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3903                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
3904         if (!NT_STATUS_IS_OK(status)) {
3905                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3906                 correct = False;
3907                 goto fail;
3908         }
3909
3910         status = cli_nt_delete_on_close(cli1, fnum1, true);
3911         if (!NT_STATUS_IS_OK(status)) {
3912                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3913                 correct = False;
3914                 goto fail;
3915         }
3916
3917         status = cli_close(cli1, fnum1);
3918         if (!NT_STATUS_IS_OK(status)) {
3919                 printf("[2] close failed (%s)\n", nt_errstr(status));
3920                 correct = False;
3921                 goto fail;
3922         }
3923
3924         if (NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3925                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3926                 status = cli_close(cli1, fnum1);
3927                 if (!NT_STATUS_IS_OK(status)) {
3928                         printf("[2] close failed (%s)\n", nt_errstr(status));
3929                         correct = False;
3930                         goto fail;
3931                 }
3932                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3933         } else
3934                 printf("second delete on close test succeeded.\n");
3935
3936         /* Test 3 - ... */
3937         cli_setatr(cli1, fname, 0, 0);
3938         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3939
3940         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3941                               FILE_ATTRIBUTE_NORMAL,
3942                               FILE_SHARE_READ|FILE_SHARE_WRITE,
3943                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
3944         if (!NT_STATUS_IS_OK(status)) {
3945                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
3946                 correct = False;
3947                 goto fail;
3948         }
3949
3950         /* This should fail with a sharing violation - open for delete is only compatible
3951            with SHARE_DELETE. */
3952
3953         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3954                               FILE_ATTRIBUTE_NORMAL,
3955                               FILE_SHARE_READ|FILE_SHARE_WRITE,
3956                               FILE_OPEN, 0, 0, &fnum2);
3957         if (NT_STATUS_IS_OK(status)) {
3958                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
3959                 correct = False;
3960                 goto fail;
3961         }
3962
3963         /* This should succeed. */
3964         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3965                              FILE_ATTRIBUTE_NORMAL,
3966                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3967                              FILE_OPEN, 0, 0, &fnum2);
3968         if (!NT_STATUS_IS_OK(status)) {
3969                 printf("[3] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
3970                 correct = False;
3971                 goto fail;
3972         }
3973
3974         status = cli_nt_delete_on_close(cli1, fnum1, true);
3975         if (!NT_STATUS_IS_OK(status)) {
3976                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
3977                 correct = False;
3978                 goto fail;
3979         }
3980
3981         status = cli_close(cli1, fnum1);
3982         if (!NT_STATUS_IS_OK(status)) {
3983                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
3984                 correct = False;
3985                 goto fail;
3986         }
3987
3988         status = cli_close(cli1, fnum2);
3989         if (!NT_STATUS_IS_OK(status)) {
3990                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
3991                 correct = False;
3992                 goto fail;
3993         }
3994
3995         /* This should fail - file should no longer be there. */
3996
3997         if (NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3998                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
3999                 status = cli_close(cli1, fnum1);
4000                 if (!NT_STATUS_IS_OK(status)) {
4001                         printf("[3] close failed (%s)\n", nt_errstr(status));
4002                 }
4003                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4004                 correct = False;
4005                 goto fail;
4006         } else
4007                 printf("third delete on close test succeeded.\n");
4008
4009         /* Test 4 ... */
4010         cli_setatr(cli1, fname, 0, 0);
4011         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4012
4013         status = cli_ntcreate(cli1, fname, 0,
4014                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4015                               FILE_ATTRIBUTE_NORMAL,
4016                               FILE_SHARE_READ|FILE_SHARE_WRITE,
4017                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4018         if (!NT_STATUS_IS_OK(status)) {
4019                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
4020                 correct = False;
4021                 goto fail;
4022         }
4023
4024         /* This should succeed. */
4025         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4026                              FILE_ATTRIBUTE_NORMAL,
4027                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4028                              FILE_OPEN, 0, 0, &fnum2);
4029         if (!NT_STATUS_IS_OK(status)) {
4030                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4031                 correct = False;
4032                 goto fail;
4033         }
4034
4035         status = cli_close(cli1, fnum2);
4036         if (!NT_STATUS_IS_OK(status)) {
4037                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4038                 correct = False;
4039                 goto fail;
4040         }
4041
4042         status = cli_nt_delete_on_close(cli1, fnum1, true);
4043         if (!NT_STATUS_IS_OK(status)) {
4044                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4045                 correct = False;
4046                 goto fail;
4047         }
4048
4049         /* This should fail - no more opens once delete on close set. */
4050         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4051                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4052                                    FILE_OPEN, 0, 0, &fnum2))) {
4053                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
4054                 correct = False;
4055                 goto fail;
4056         } else
4057                 printf("fourth delete on close test succeeded.\n");
4058
4059         status = cli_close(cli1, fnum1);
4060         if (!NT_STATUS_IS_OK(status)) {
4061                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4062                 correct = False;
4063                 goto fail;
4064         }
4065
4066         /* Test 5 ... */
4067         cli_setatr(cli1, fname, 0, 0);
4068         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4069
4070         status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4071         if (!NT_STATUS_IS_OK(status)) {
4072                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4073                 correct = False;
4074                 goto fail;
4075         }
4076
4077         /* This should fail - only allowed on NT opens with DELETE access. */
4078
4079         if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4080                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4081                 correct = False;
4082                 goto fail;
4083         }
4084
4085         status = cli_close(cli1, fnum1);
4086         if (!NT_STATUS_IS_OK(status)) {
4087                 printf("[5] close - 2 failed (%s)\n", nt_errstr(status));
4088                 correct = False;
4089                 goto fail;
4090         }
4091
4092         printf("fifth delete on close test succeeded.\n");
4093
4094         /* Test 6 ... */
4095         cli_setatr(cli1, fname, 0, 0);
4096         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4097
4098         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4099                              FILE_ATTRIBUTE_NORMAL,
4100                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4101                              FILE_OVERWRITE_IF, 0, 0, &fnum1);
4102         if (!NT_STATUS_IS_OK(status)) {
4103                 printf("[6] open of %s failed (%s)\n", fname,
4104                        nt_errstr(status));
4105                 correct = False;
4106                 goto fail;
4107         }
4108
4109         /* This should fail - only allowed on NT opens with DELETE access. */
4110
4111         if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4112                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4113                 correct = False;
4114                 goto fail;
4115         }
4116
4117         status = cli_close(cli1, fnum1);
4118         if (!NT_STATUS_IS_OK(status)) {
4119                 printf("[6] close - 2 failed (%s)\n", nt_errstr(status));
4120                 correct = False;
4121                 goto fail;
4122         }
4123
4124         printf("sixth delete on close test succeeded.\n");
4125
4126         /* Test 7 ... */
4127         cli_setatr(cli1, fname, 0, 0);
4128         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4129
4130         status = cli_ntcreate(cli1, fname, 0,
4131                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4132                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4133                               0, 0, &fnum1);
4134         if (!NT_STATUS_IS_OK(status)) {
4135                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4136                 correct = False;
4137                 goto fail;
4138         }
4139
4140         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4141                 printf("[7] setting delete_on_close on file failed !\n");
4142                 correct = False;
4143                 goto fail;
4144         }
4145
4146         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, false))) {
4147                 printf("[7] unsetting delete_on_close on file failed !\n");
4148                 correct = False;
4149                 goto fail;
4150         }
4151
4152         status = cli_close(cli1, fnum1);
4153         if (!NT_STATUS_IS_OK(status)) {
4154                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4155                 correct = False;
4156                 goto fail;
4157         }
4158
4159         /* This next open should succeed - we reset the flag. */
4160         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4161         if (!NT_STATUS_IS_OK(status)) {
4162                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4163                 correct = False;
4164                 goto fail;
4165         }
4166
4167         status = cli_close(cli1, fnum1);
4168         if (!NT_STATUS_IS_OK(status)) {
4169                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4170                 correct = False;
4171                 goto fail;
4172         }
4173
4174         printf("seventh delete on close test succeeded.\n");
4175
4176         /* Test 7 ... */
4177         cli_setatr(cli1, fname, 0, 0);
4178         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4179
4180         if (!torture_open_connection(&cli2, 1)) {
4181                 printf("[8] failed to open second connection.\n");
4182                 correct = False;
4183                 goto fail;
4184         }
4185
4186         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4187
4188         status = cli_ntcreate(cli1, fname, 0,
4189                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4190                              FILE_ATTRIBUTE_NORMAL,
4191                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4192                              FILE_OVERWRITE_IF, 0, 0, &fnum1);
4193         if (!NT_STATUS_IS_OK(status)) {
4194                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4195                 correct = False;
4196                 goto fail;
4197         }
4198
4199         status = cli_ntcreate(cli2, fname, 0,
4200                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4201                              FILE_ATTRIBUTE_NORMAL,
4202                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4203                              FILE_OPEN, 0, 0, &fnum2);
4204         if (!NT_STATUS_IS_OK(status)) {
4205                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4206                 correct = False;
4207                 goto fail;
4208         }
4209
4210         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4211                 printf("[8] setting delete_on_close on file failed !\n");
4212                 correct = False;
4213                 goto fail;
4214         }
4215
4216         status = cli_close(cli1, fnum1);
4217         if (!NT_STATUS_IS_OK(status)) {
4218                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4219                 correct = False;
4220                 goto fail;
4221         }
4222
4223         status = cli_close(cli2, fnum2);
4224         if (!NT_STATUS_IS_OK(status)) {
4225                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4226                 correct = False;
4227                 goto fail;
4228         }
4229
4230         /* This should fail.. */
4231         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4232         if (NT_STATUS_IS_OK(status)) {
4233                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4234                 goto fail;
4235                 correct = False;
4236         } else
4237                 printf("eighth delete on close test succeeded.\n");
4238
4239         /* This should fail - we need to set DELETE_ACCESS. */
4240         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,FILE_READ_DATA|FILE_WRITE_DATA,
4241                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
4242                 printf("[9] open of %s succeeded should have failed!\n", fname);
4243                 correct = False;
4244                 goto fail;
4245         }
4246
4247         printf("ninth delete on close test succeeded.\n");
4248
4249         status = cli_ntcreate(cli1, fname, 0,
4250                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4251                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4252                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4253                              0, &fnum1);
4254         if (!NT_STATUS_IS_OK(status)) {
4255                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4256                 correct = False;
4257                 goto fail;
4258         }
4259
4260         /* This should delete the file. */
4261         status = cli_close(cli1, fnum1);
4262         if (!NT_STATUS_IS_OK(status)) {
4263                 printf("[10] close failed (%s)\n", nt_errstr(status));
4264                 correct = False;
4265                 goto fail;
4266         }
4267
4268         /* This should fail.. */
4269         if (NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4270                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4271                 goto fail;
4272                 correct = False;
4273         } else
4274                 printf("tenth delete on close test succeeded.\n");
4275
4276         cli_setatr(cli1, fname, 0, 0);
4277         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4278
4279         /* What error do we get when attempting to open a read-only file with
4280            delete access ? */
4281
4282         /* Create a readonly file. */
4283         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4284                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4285                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4286         if (!NT_STATUS_IS_OK(status)) {
4287                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4288                 correct = False;
4289                 goto fail;
4290         }
4291
4292         status = cli_close(cli1, fnum1);
4293         if (!NT_STATUS_IS_OK(status)) {
4294                 printf("[11] close failed (%s)\n", nt_errstr(status));
4295                 correct = False;
4296                 goto fail;
4297         }
4298
4299         /* Now try open for delete access. */
4300         status = cli_ntcreate(cli1, fname, 0,
4301                              FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4302                              0,
4303                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4304                              FILE_OVERWRITE_IF, 0, 0, &fnum1);
4305         if (NT_STATUS_IS_OK(status)) {
4306                 printf("[11] open of %s succeeded should have been denied with ACCESS_DENIED!\n", fname);
4307                 cli_close(cli1, fnum1);
4308                 goto fail;
4309                 correct = False;
4310         } else {
4311                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
4312                         printf("[11] open of %s should have been denied with ACCESS_DENIED! Got error %s\n", fname, nt_errstr(status));
4313                         goto fail;
4314                         correct = False;
4315                 } else {
4316                         printf("eleventh delete on close test succeeded.\n");
4317                 }
4318         }
4319
4320         printf("finished delete test\n");
4321
4322   fail:
4323         /* FIXME: This will crash if we aborted before cli2 got
4324          * intialized, because these functions don't handle
4325          * uninitialized connections. */
4326
4327         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4328         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4329         cli_setatr(cli1, fname, 0, 0);
4330         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4331
4332         if (cli1 && !torture_close_connection(cli1)) {
4333                 correct = False;
4334         }
4335         if (cli2 && !torture_close_connection(cli2)) {
4336                 correct = False;
4337         }
4338         return correct;
4339 }
4340
4341 static bool run_deletetest_ln(int dummy)
4342 {
4343         struct cli_state *cli;
4344         const char *fname = "\\delete1";
4345         const char *fname_ln = "\\delete1_ln";
4346         uint16_t fnum;
4347         uint16_t fnum1;
4348         NTSTATUS status;
4349         bool correct = true;
4350         time_t t;
4351
4352         printf("starting deletetest-ln\n");
4353
4354         if (!torture_open_connection(&cli, 0)) {
4355                 return false;
4356         }
4357
4358         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4359         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4360
4361         smbXcli_conn_set_sockopt(cli->conn, sockops);
4362
4363         /* Create the file. */
4364         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4365         if (!NT_STATUS_IS_OK(status)) {
4366                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4367                 return false;
4368         }
4369
4370         status = cli_close(cli, fnum);
4371         if (!NT_STATUS_IS_OK(status)) {
4372                 printf("close1 failed (%s)\n", nt_errstr(status));
4373                 return false;
4374         }
4375
4376         /* Now create a hardlink. */
4377         status = cli_nt_hardlink(cli, fname, fname_ln);
4378         if (!NT_STATUS_IS_OK(status)) {
4379                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4380                 return false;
4381         }
4382
4383         /* Open the original file. */
4384         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4385                         FILE_ATTRIBUTE_NORMAL,
4386                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4387                         FILE_OPEN_IF, 0, 0, &fnum);
4388         if (!NT_STATUS_IS_OK(status)) {
4389                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4390                 return false;
4391         }
4392
4393         /* Unlink the hard link path. */
4394         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4395                         FILE_ATTRIBUTE_NORMAL,
4396                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4397                         FILE_OPEN_IF, 0, 0, &fnum1);
4398         if (!NT_STATUS_IS_OK(status)) {
4399                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4400                 return false;
4401         }
4402         status = cli_nt_delete_on_close(cli, fnum1, true);
4403         if (!NT_STATUS_IS_OK(status)) {
4404                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4405                         __location__, fname_ln, nt_errstr(status));
4406                 return false;
4407         }
4408
4409         status = cli_close(cli, fnum1);
4410         if (!NT_STATUS_IS_OK(status)) {
4411                 printf("close %s failed (%s)\n",
4412                         fname_ln, nt_errstr(status));
4413                 return false;
4414         }
4415
4416         status = cli_close(cli, fnum);
4417         if (!NT_STATUS_IS_OK(status)) {
4418                 printf("close %s failed (%s)\n",
4419                         fname, nt_errstr(status));
4420                 return false;
4421         }
4422
4423         /* Ensure the original file is still there. */
4424         status = cli_getatr(cli, fname, NULL, NULL, &t);
4425         if (!NT_STATUS_IS_OK(status)) {
4426                 printf("%s getatr on file %s failed (%s)\n",
4427                         __location__,
4428                         fname,
4429                         nt_errstr(status));
4430                 correct = False;
4431         }
4432
4433         /* Ensure the link path is gone. */
4434         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4435         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4436                 printf("%s, getatr for file %s returned wrong error code %s "
4437                         "- should have been deleted\n",
4438                         __location__,
4439                         fname_ln, nt_errstr(status));
4440                 correct = False;
4441         }
4442
4443         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4444         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4445
4446         if (!torture_close_connection(cli)) {
4447                 correct = false;
4448         }
4449
4450         printf("finished deletetest-ln\n");
4451
4452         return correct;
4453 }
4454
4455 /*
4456   print out server properties
4457  */
4458 static bool run_properties(int dummy)
4459 {
4460         struct cli_state *cli;
4461         bool correct = True;
4462
4463         printf("starting properties test\n");
4464
4465         ZERO_STRUCT(cli);
4466
4467         if (!torture_open_connection(&cli, 0)) {
4468                 return False;
4469         }
4470
4471         smbXcli_conn_set_sockopt(cli->conn, sockops);
4472
4473         d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
4474
4475         if (!torture_close_connection(cli)) {
4476                 correct = False;
4477         }
4478
4479         return correct;
4480 }
4481
4482
4483
4484 /* FIRST_DESIRED_ACCESS   0xf019f */
4485 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4486                                FILE_READ_EA|                           /* 0xf */ \
4487                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
4488                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
4489                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
4490                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
4491 /* SECOND_DESIRED_ACCESS  0xe0080 */
4492 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4493                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4494                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
4495
4496 #if 0
4497 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4498                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4499                                FILE_READ_DATA|\
4500                                WRITE_OWNER_ACCESS                      /* */
4501 #endif
4502
4503 /*
4504   Test ntcreate calls made by xcopy
4505  */
4506 static bool run_xcopy(int dummy)
4507 {
4508         static struct cli_state *cli1;
4509         const char *fname = "\\test.txt";
4510         bool correct = True;
4511         uint16_t fnum1, fnum2;
4512         NTSTATUS status;
4513
4514         printf("starting xcopy test\n");
4515
4516         if (!torture_open_connection(&cli1, 0)) {
4517                 return False;
4518         }
4519
4520         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4521                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4522                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1);
4523         if (!NT_STATUS_IS_OK(status)) {
4524                 printf("First open failed - %s\n", nt_errstr(status));
4525                 return False;
4526         }
4527
4528         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4529                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4530                              FILE_OPEN, 0x200000, 0, &fnum2);
4531         if (!NT_STATUS_IS_OK(status)) {
4532                 printf("second open failed - %s\n", nt_errstr(status));
4533                 return False;
4534         }
4535
4536         if (!torture_close_connection(cli1)) {
4537                 correct = False;
4538         }
4539
4540         return correct;
4541 }
4542
4543 /*
4544   Test rename on files open with share delete and no share delete.
4545  */
4546 static bool run_rename(int dummy)
4547 {
4548         static struct cli_state *cli1;
4549         const char *fname = "\\test.txt";
4550         const char *fname1 = "\\test1.txt";
4551         bool correct = True;
4552         uint16_t fnum1;
4553         uint16_t attr;
4554         NTSTATUS status;
4555
4556         printf("starting rename test\n");
4557
4558         if (!torture_open_connection(&cli1, 0)) {
4559                 return False;
4560         }
4561
4562         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4563         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4564
4565         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4566                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4567                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4568         if (!NT_STATUS_IS_OK(status)) {
4569                 printf("First open failed - %s\n", nt_errstr(status));
4570                 return False;
4571         }
4572
4573         status = cli_rename(cli1, fname, fname1);
4574         if (!NT_STATUS_IS_OK(status)) {
4575                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4576         } else {
4577                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4578                 correct = False;
4579         }
4580
4581         status = cli_close(cli1, fnum1);
4582         if (!NT_STATUS_IS_OK(status)) {
4583                 printf("close - 1 failed (%s)\n", nt_errstr(status));
4584                 return False;
4585         }
4586
4587         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4588         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4589         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4590 #if 0
4591                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
4592 #else
4593                               FILE_SHARE_DELETE|FILE_SHARE_READ,
4594 #endif
4595                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4596         if (!NT_STATUS_IS_OK(status)) {
4597                 printf("Second open failed - %s\n", nt_errstr(status));
4598                 return False;
4599         }
4600
4601         status = cli_rename(cli1, fname, fname1);
4602         if (!NT_STATUS_IS_OK(status)) {
4603                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4604                 correct = False;
4605         } else {
4606                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4607         }
4608
4609         status = cli_close(cli1, fnum1);
4610         if (!NT_STATUS_IS_OK(status)) {
4611                 printf("close - 2 failed (%s)\n", nt_errstr(status));
4612                 return False;
4613         }
4614
4615         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4616         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4617
4618         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4619                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4620                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4621         if (!NT_STATUS_IS_OK(status)) {
4622                 printf("Third open failed - %s\n", nt_errstr(status));
4623                 return False;
4624         }
4625
4626
4627 #if 0
4628   {
4629         uint16_t fnum2;
4630
4631         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4632                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4633                 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4634                 return False;
4635         }
4636         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4637                 printf("[8] setting delete_on_close on file failed !\n");
4638                 return False;
4639         }
4640
4641         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4642                 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4643                 return False;
4644         }
4645   }
4646 #endif
4647
4648         status = cli_rename(cli1, fname, fname1);
4649         if (!NT_STATUS_IS_OK(status)) {
4650                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4651                 correct = False;
4652         } else {
4653                 printf("Third rename succeeded (SHARE_NONE)\n");
4654         }
4655
4656         status = cli_close(cli1, fnum1);
4657         if (!NT_STATUS_IS_OK(status)) {
4658                 printf("close - 3 failed (%s)\n", nt_errstr(status));
4659                 return False;
4660         }
4661
4662         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4663         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4664
4665         /*----*/
4666
4667         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4668                               FILE_ATTRIBUTE_NORMAL,
4669                               FILE_SHARE_READ | FILE_SHARE_WRITE,
4670                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4671         if (!NT_STATUS_IS_OK(status)) {
4672                 printf("Fourth open failed - %s\n", nt_errstr(status));
4673                 return False;
4674         }
4675
4676         status = cli_rename(cli1, fname, fname1);
4677         if (!NT_STATUS_IS_OK(status)) {
4678                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4679         } else {
4680                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4681                 correct = False;
4682         }
4683
4684         status = cli_close(cli1, fnum1);
4685         if (!NT_STATUS_IS_OK(status)) {
4686                 printf("close - 4 failed (%s)\n", nt_errstr(status));
4687                 return False;
4688         }
4689
4690         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4691         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4692
4693         /*--*/
4694
4695         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4696                          FILE_ATTRIBUTE_NORMAL,
4697                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4698                          FILE_OVERWRITE_IF, 0, 0, &fnum1);
4699         if (!NT_STATUS_IS_OK(status)) {
4700                 printf("Fifth open failed - %s\n", nt_errstr(status));
4701                 return False;
4702         }
4703
4704         status = cli_rename(cli1, fname, fname1);
4705         if (!NT_STATUS_IS_OK(status)) {
4706                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4707                 correct = False;
4708         } else {
4709                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4710         }
4711
4712         /*
4713          * Now check if the first name still exists ...
4714          */
4715
4716         /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4717                                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4718           printf("Opening original file after rename of open file fails: %s\n",
4719               cli_errstr(cli1));
4720         }
4721         else {
4722           printf("Opening original file after rename of open file works ...\n");
4723           (void)cli_close(cli1, fnum2);
4724           } */
4725
4726         /*--*/
4727         status = cli_close(cli1, fnum1);
4728         if (!NT_STATUS_IS_OK(status)) {
4729                 printf("close - 5 failed (%s)\n", nt_errstr(status));
4730                 return False;
4731         }
4732
4733         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4734         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4735         if (!NT_STATUS_IS_OK(status)) {
4736                 printf("getatr on file %s failed - %s ! \n",
4737                         fname1, nt_errstr(status));
4738                 correct = False;
4739         } else {
4740                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4741                         printf("Renamed file %s has wrong attr 0x%x "
4742                                 "(should be 0x%x)\n",
4743                                 fname1,
4744                                 attr,
4745                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4746                         correct = False;
4747                 } else {
4748                         printf("Renamed file %s has archive bit set\n", fname1);
4749                 }
4750         }
4751
4752         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4753         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4754
4755         if (!torture_close_connection(cli1)) {
4756                 correct = False;
4757         }
4758
4759         return correct;
4760 }
4761
4762 static bool run_pipe_number(int dummy)
4763 {
4764         struct cli_state *cli1;
4765         const char *pipe_name = "\\SPOOLSS";
4766         uint16_t fnum;
4767         int num_pipes = 0;
4768         NTSTATUS status;
4769
4770         printf("starting pipenumber test\n");
4771         if (!torture_open_connection(&cli1, 0)) {
4772                 return False;
4773         }
4774
4775         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4776         while(1) {
4777                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
4778                                       FILE_ATTRIBUTE_NORMAL,
4779                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
4780                                       FILE_OPEN_IF, 0, 0, &fnum);
4781                 if (!NT_STATUS_IS_OK(status)) {
4782                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
4783                         break;
4784                 }
4785                 num_pipes++;
4786                 printf("\r%6d", num_pipes);
4787         }
4788
4789         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4790         torture_close_connection(cli1);
4791         return True;
4792 }
4793
4794 /*
4795   Test open mode returns on read-only files.
4796  */
4797 static bool run_opentest(int dummy)
4798 {
4799         static struct cli_state *cli1;
4800         static struct cli_state *cli2;
4801         const char *fname = "\\readonly.file";
4802         uint16_t fnum1, fnum2;
4803         char buf[20];
4804         off_t fsize;
4805         bool correct = True;
4806         char *tmp_path;
4807         NTSTATUS status;
4808
4809         printf("starting open test\n");
4810
4811         if (!torture_open_connection(&cli1, 0)) {
4812                 return False;
4813         }
4814
4815         cli_setatr(cli1, fname, 0, 0);
4816         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4817
4818         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4819
4820         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4821         if (!NT_STATUS_IS_OK(status)) {
4822                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4823                 return False;
4824         }
4825
4826         status = cli_close(cli1, fnum1);
4827         if (!NT_STATUS_IS_OK(status)) {
4828                 printf("close2 failed (%s)\n", nt_errstr(status));
4829                 return False;
4830         }
4831
4832         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
4833         if (!NT_STATUS_IS_OK(status)) {
4834                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
4835                 return False;
4836         }
4837
4838         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4839         if (!NT_STATUS_IS_OK(status)) {
4840                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4841                 return False;
4842         }
4843
4844         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4845         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4846
4847         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
4848                         NT_STATUS_ACCESS_DENIED)) {
4849                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4850         }
4851
4852         printf("finished open test 1\n");
4853
4854         cli_close(cli1, fnum1);
4855
4856         /* Now try not readonly and ensure ERRbadshare is returned. */
4857
4858         cli_setatr(cli1, fname, 0, 0);
4859
4860         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4861         if (!NT_STATUS_IS_OK(status)) {
4862                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4863                 return False;
4864         }
4865
4866         /* This will fail - but the error should be ERRshare. */
4867         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4868
4869         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
4870                         NT_STATUS_SHARING_VIOLATION)) {
4871                 printf("correct error code ERRDOS/ERRbadshare returned\n");
4872         }
4873
4874         status = cli_close(cli1, fnum1);
4875         if (!NT_STATUS_IS_OK(status)) {
4876                 printf("close2 failed (%s)\n", nt_errstr(status));
4877                 return False;
4878         }
4879
4880         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4881
4882         printf("finished open test 2\n");
4883
4884         /* Test truncate open disposition on file opened for read. */
4885         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4886         if (!NT_STATUS_IS_OK(status)) {
4887                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
4888                 return False;
4889         }
4890
4891         /* write 20 bytes. */
4892
4893         memset(buf, '\0', 20);
4894
4895         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
4896         if (!NT_STATUS_IS_OK(status)) {
4897                 printf("write failed (%s)\n", nt_errstr(status));
4898                 correct = False;
4899         }
4900
4901         status = cli_close(cli1, fnum1);
4902         if (!NT_STATUS_IS_OK(status)) {
4903                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
4904                 return False;
4905         }
4906
4907         /* Ensure size == 20. */
4908         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4909         if (!NT_STATUS_IS_OK(status)) {
4910                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4911                 return False;
4912         }
4913
4914         if (fsize != 20) {
4915                 printf("(3) file size != 20\n");
4916                 return False;
4917         }
4918
4919         /* Now test if we can truncate a file opened for readonly. */
4920         status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
4921         if (!NT_STATUS_IS_OK(status)) {
4922                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
4923                 return False;
4924         }
4925
4926         status = cli_close(cli1, fnum1);
4927         if (!NT_STATUS_IS_OK(status)) {
4928                 printf("close2 failed (%s)\n", nt_errstr(status));
4929                 return False;
4930         }
4931
4932         /* Ensure size == 0. */
4933         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4934         if (!NT_STATUS_IS_OK(status)) {
4935                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4936                 return False;
4937         }
4938
4939         if (fsize != 0) {
4940                 printf("(3) file size != 0\n");
4941                 return False;
4942         }
4943         printf("finished open test 3\n");
4944
4945         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4946
4947         printf("Do ctemp tests\n");
4948         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
4949         if (!NT_STATUS_IS_OK(status)) {
4950                 printf("ctemp failed (%s)\n", nt_errstr(status));
4951                 return False;
4952         }
4953
4954         printf("ctemp gave path %s\n", tmp_path);
4955         status = cli_close(cli1, fnum1);
4956         if (!NT_STATUS_IS_OK(status)) {
4957                 printf("close of temp failed (%s)\n", nt_errstr(status));
4958         }
4959
4960         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4961         if (!NT_STATUS_IS_OK(status)) {
4962                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
4963         }
4964
4965         /* Test the non-io opens... */
4966
4967         if (!torture_open_connection(&cli2, 1)) {
4968                 return False;
4969         }
4970
4971         cli_setatr(cli2, fname, 0, 0);
4972         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4973
4974         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4975
4976         printf("TEST #1 testing 2 non-io opens (no delete)\n");
4977         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
4978                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4979                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4980         if (!NT_STATUS_IS_OK(status)) {
4981                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4982                 return False;
4983         }
4984
4985         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
4986                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4987                               FILE_OPEN_IF, 0, 0, &fnum2);
4988         if (!NT_STATUS_IS_OK(status)) {
4989                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4990                 return False;
4991         }
4992
4993         status = cli_close(cli1, fnum1);
4994         if (!NT_STATUS_IS_OK(status)) {
4995                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
4996                 return False;
4997         }
4998
4999         status = cli_close(cli2, fnum2);
5000         if (!NT_STATUS_IS_OK(status)) {
5001                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5002                 return False;
5003         }
5004
5005         printf("non-io open test #1 passed.\n");
5006
5007         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5008
5009         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5010
5011         status = cli_ntcreate(cli1, fname, 0,
5012                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5013                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5014                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5015         if (!NT_STATUS_IS_OK(status)) {
5016                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5017                 return False;
5018         }
5019
5020         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5021                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5022                               FILE_OPEN_IF, 0, 0, &fnum2);
5023         if (!NT_STATUS_IS_OK(status)) {
5024                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5025                 return False;
5026         }
5027
5028         status = cli_close(cli1, fnum1);
5029         if (!NT_STATUS_IS_OK(status)) {
5030                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5031                 return False;
5032         }
5033
5034         status = cli_close(cli2, fnum2);
5035         if (!NT_STATUS_IS_OK(status)) {
5036                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5037                 return False;
5038         }
5039
5040         printf("non-io open test #2 passed.\n");
5041
5042         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5043
5044         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5045
5046         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5047                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5048                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5049         if (!NT_STATUS_IS_OK(status)) {
5050                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5051                 return False;
5052         }
5053
5054         status = cli_ntcreate(cli2, fname, 0,
5055                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5056                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5057                               FILE_OPEN_IF, 0, 0, &fnum2);
5058         if (!NT_STATUS_IS_OK(status)) {
5059                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5060                 return False;
5061         }
5062
5063         status = cli_close(cli1, fnum1);
5064         if (!NT_STATUS_IS_OK(status)) {
5065                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5066                 return False;
5067         }
5068
5069         status = cli_close(cli2, fnum2);
5070         if (!NT_STATUS_IS_OK(status)) {
5071                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5072                 return False;
5073         }
5074
5075         printf("non-io open test #3 passed.\n");
5076
5077         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5078
5079         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5080
5081         status = cli_ntcreate(cli1, fname, 0,
5082                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5083                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5084                                FILE_OVERWRITE_IF, 0, 0, &fnum1);
5085         if (!NT_STATUS_IS_OK(status)) {
5086                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5087                 return False;
5088         }
5089
5090         status = cli_ntcreate(cli2, fname, 0,
5091                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5092                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5093                               FILE_OPEN_IF, 0, 0, &fnum2);
5094         if (NT_STATUS_IS_OK(status)) {
5095                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5096                 return False;
5097         }
5098
5099         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5100
5101         status = cli_close(cli1, fnum1);
5102         if (!NT_STATUS_IS_OK(status)) {
5103                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5104                 return False;
5105         }
5106
5107         printf("non-io open test #4 passed.\n");
5108
5109         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5110
5111         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5112
5113         status = cli_ntcreate(cli1, fname, 0,
5114                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5115                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5116                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5117         if (!NT_STATUS_IS_OK(status)) {
5118                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5119                 return False;
5120         }
5121
5122         status = cli_ntcreate(cli2, fname, 0,
5123                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5124                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5125                               FILE_OPEN_IF, 0, 0, &fnum2);
5126         if (!NT_STATUS_IS_OK(status)) {
5127                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5128                 return False;
5129         }
5130
5131         status = cli_close(cli1, fnum1);
5132         if (!NT_STATUS_IS_OK(status)) {
5133                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5134                 return False;
5135         }
5136
5137         status = cli_close(cli2, fnum2);
5138         if (!NT_STATUS_IS_OK(status)) {
5139                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5140                 return False;
5141         }
5142
5143         printf("non-io open test #5 passed.\n");
5144
5145         printf("TEST #6 testing 1 non-io open, one io open\n");
5146
5147         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5148
5149         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5150                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5151                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5152         if (!NT_STATUS_IS_OK(status)) {
5153                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5154                 return False;
5155         }
5156
5157         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5158                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5159                               FILE_OPEN_IF, 0, 0, &fnum2);
5160         if (!NT_STATUS_IS_OK(status)) {
5161                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5162                 return False;
5163         }
5164
5165         status = cli_close(cli1, fnum1);
5166         if (!NT_STATUS_IS_OK(status)) {
5167                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5168                 return False;
5169         }
5170
5171         status = cli_close(cli2, fnum2);
5172         if (!NT_STATUS_IS_OK(status)) {
5173                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5174                 return False;
5175         }
5176
5177         printf("non-io open test #6 passed.\n");
5178
5179         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5180
5181         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5182
5183         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5184                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5185                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5186         if (!NT_STATUS_IS_OK(status)) {
5187                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5188                 return False;
5189         }
5190
5191         status = cli_ntcreate(cli2, fname, 0,
5192                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5193                               FILE_ATTRIBUTE_NORMAL,
5194                               FILE_SHARE_READ|FILE_SHARE_DELETE,
5195                               FILE_OPEN_IF, 0, 0, &fnum2);
5196         if (NT_STATUS_IS_OK(status)) {
5197                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5198                 return False;
5199         }
5200
5201         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5202
5203         status = cli_close(cli1, fnum1);
5204         if (!NT_STATUS_IS_OK(status)) {
5205                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5206                 return False;
5207         }
5208
5209         printf("non-io open test #7 passed.\n");
5210
5211         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5212
5213         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5214         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5215                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5216                                 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5217         if (!NT_STATUS_IS_OK(status)) {
5218                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5219                 correct = false;
5220                 goto out;
5221         }
5222
5223         /* Write to ensure we have to update the file time. */
5224         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5225                               NULL);
5226         if (!NT_STATUS_IS_OK(status)) {
5227                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5228                 correct = false;
5229                 goto out;
5230         }
5231
5232         status = cli_close(cli1, fnum1);
5233         if (!NT_STATUS_IS_OK(status)) {
5234                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5235                 correct = false;
5236         }
5237
5238   out:
5239
5240         if (!torture_close_connection(cli1)) {
5241                 correct = False;
5242         }
5243         if (!torture_close_connection(cli2)) {
5244                 correct = False;
5245         }
5246
5247         return correct;
5248 }
5249
5250 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5251 {
5252         uint16 major, minor;
5253         uint32 caplow, caphigh;
5254         NTSTATUS status;
5255
5256         if (!SERVER_HAS_UNIX_CIFS(cli)) {
5257                 printf("Server doesn't support UNIX CIFS extensions.\n");
5258                 return NT_STATUS_NOT_SUPPORTED;
5259         }
5260
5261         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5262                                              &caphigh);
5263         if (!NT_STATUS_IS_OK(status)) {
5264                 printf("Server didn't return UNIX CIFS extensions: %s\n",
5265                        nt_errstr(status));
5266                 return status;
5267         }
5268
5269         status = cli_set_unix_extensions_capabilities(cli, major, minor,
5270                                                       caplow, caphigh);
5271         if (!NT_STATUS_IS_OK(status)) {
5272                 printf("Server doesn't support setting UNIX CIFS extensions: "
5273                        "%s.\n", nt_errstr(status));
5274                 return status;
5275         }
5276
5277         return NT_STATUS_OK;
5278 }
5279
5280 /*
5281   Test POSIX open /mkdir calls.
5282  */
5283 static bool run_simple_posix_open_test(int dummy)
5284 {
5285         static struct cli_state *cli1;
5286         const char *fname = "posix:file";
5287         const char *hname = "posix:hlink";
5288         const char *sname = "posix:symlink";
5289         const char *dname = "posix:dir";
5290         char buf[10];
5291         char namebuf[11];
5292         uint16_t fnum1 = (uint16_t)-1;
5293         SMB_STRUCT_STAT sbuf;
5294         bool correct = false;
5295         NTSTATUS status;
5296         size_t nread;
5297
5298         printf("Starting simple POSIX open test\n");
5299
5300         if (!torture_open_connection(&cli1, 0)) {
5301                 return false;
5302         }
5303
5304         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5305
5306         status = torture_setup_unix_extensions(cli1);
5307         if (!NT_STATUS_IS_OK(status)) {
5308                 return false;
5309         }
5310
5311         cli_setatr(cli1, fname, 0, 0);
5312         cli_posix_unlink(cli1, fname);
5313         cli_setatr(cli1, dname, 0, 0);
5314         cli_posix_rmdir(cli1, dname);
5315         cli_setatr(cli1, hname, 0, 0);
5316         cli_posix_unlink(cli1, hname);
5317         cli_setatr(cli1, sname, 0, 0);
5318         cli_posix_unlink(cli1, sname);
5319
5320         /* Create a directory. */
5321         status = cli_posix_mkdir(cli1, dname, 0777);
5322         if (!NT_STATUS_IS_OK(status)) {
5323                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5324                 goto out;
5325         }
5326
5327         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5328                                 0600, &fnum1);
5329         if (!NT_STATUS_IS_OK(status)) {
5330                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5331                 goto out;
5332         }
5333
5334         /* Test ftruncate - set file size. */
5335         status = cli_ftruncate(cli1, fnum1, 1000);
5336         if (!NT_STATUS_IS_OK(status)) {
5337                 printf("ftruncate failed (%s)\n", nt_errstr(status));
5338                 goto out;
5339         }
5340
5341         /* Ensure st_size == 1000 */
5342         status = cli_posix_stat(cli1, fname, &sbuf);
5343         if (!NT_STATUS_IS_OK(status)) {
5344                 printf("stat failed (%s)\n", nt_errstr(status));
5345                 goto out;
5346         }
5347
5348         if (sbuf.st_ex_size != 1000) {
5349                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5350                 goto out;
5351         }
5352
5353         /* Ensure st_mode == 0600 */
5354         if ((sbuf.st_ex_mode & 07777) != 0600) {
5355                 printf("posix_open - bad permissions 0%o != 0600\n",
5356                                 (unsigned int)(sbuf.st_ex_mode & 07777));
5357                 goto out;
5358         }
5359
5360         /* Test ftruncate - set file size back to zero. */
5361         status = cli_ftruncate(cli1, fnum1, 0);
5362         if (!NT_STATUS_IS_OK(status)) {
5363                 printf("ftruncate failed (%s)\n", nt_errstr(status));
5364                 goto out;
5365         }
5366
5367         status = cli_close(cli1, fnum1);
5368         if (!NT_STATUS_IS_OK(status)) {
5369                 printf("close failed (%s)\n", nt_errstr(status));
5370                 goto out;
5371         }
5372
5373         /* Now open the file again for read only. */
5374         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5375         if (!NT_STATUS_IS_OK(status)) {
5376                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5377                 goto out;
5378         }
5379
5380         /* Now unlink while open. */
5381         status = cli_posix_unlink(cli1, fname);
5382         if (!NT_STATUS_IS_OK(status)) {
5383                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5384                 goto out;
5385         }
5386
5387         status = cli_close(cli1, fnum1);
5388         if (!NT_STATUS_IS_OK(status)) {
5389                 printf("close(2) failed (%s)\n", nt_errstr(status));
5390                 goto out;
5391         }
5392
5393         /* Ensure the file has gone. */
5394         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5395         if (NT_STATUS_IS_OK(status)) {
5396                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5397                 goto out;
5398         }
5399
5400         /* Create again to test open with O_TRUNC. */
5401         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
5402         if (!NT_STATUS_IS_OK(status)) {
5403                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5404                 goto out;
5405         }
5406
5407         /* Test ftruncate - set file size. */
5408         status = cli_ftruncate(cli1, fnum1, 1000);
5409         if (!NT_STATUS_IS_OK(status)) {
5410                 printf("ftruncate failed (%s)\n", nt_errstr(status));
5411                 goto out;
5412         }
5413
5414         /* Ensure st_size == 1000 */
5415         status = cli_posix_stat(cli1, fname, &sbuf);
5416         if (!NT_STATUS_IS_OK(status)) {
5417                 printf("stat failed (%s)\n", nt_errstr(status));
5418                 goto out;
5419         }
5420
5421         if (sbuf.st_ex_size != 1000) {
5422                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5423                 goto out;
5424         }
5425
5426         status = cli_close(cli1, fnum1);
5427         if (!NT_STATUS_IS_OK(status)) {
5428                 printf("close(2) failed (%s)\n", nt_errstr(status));
5429                 goto out;
5430         }
5431
5432         /* Re-open with O_TRUNC. */
5433         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
5434         if (!NT_STATUS_IS_OK(status)) {
5435                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5436                 goto out;
5437         }
5438
5439         /* Ensure st_size == 0 */
5440         status = cli_posix_stat(cli1, fname, &sbuf);
5441         if (!NT_STATUS_IS_OK(status)) {
5442                 printf("stat failed (%s)\n", nt_errstr(status));
5443                 goto out;
5444         }
5445
5446         if (sbuf.st_ex_size != 0) {
5447                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5448                 goto out;
5449         }
5450
5451         status = cli_close(cli1, fnum1);
5452         if (!NT_STATUS_IS_OK(status)) {
5453                 printf("close failed (%s)\n", nt_errstr(status));
5454                 goto out;
5455         }
5456
5457         status = cli_posix_unlink(cli1, fname);
5458         if (!NT_STATUS_IS_OK(status)) {
5459                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5460                 goto out;
5461         }
5462
5463         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
5464         if (!NT_STATUS_IS_OK(status)) {
5465                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5466                         dname, nt_errstr(status));
5467                 goto out;
5468         }
5469
5470         cli_close(cli1, fnum1);
5471
5472         /* What happens when we try and POSIX open a directory for write ? */
5473         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
5474         if (NT_STATUS_IS_OK(status)) {
5475                 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5476                 goto out;
5477         } else {
5478                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
5479                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5480                         goto out;
5481                 }
5482         }
5483
5484         /* Create the file. */
5485         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5486                                 0600, &fnum1);
5487         if (!NT_STATUS_IS_OK(status)) {
5488                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5489                 goto out;
5490         }
5491
5492         /* Write some data into it. */
5493         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5494                               NULL);
5495         if (!NT_STATUS_IS_OK(status)) {
5496                 printf("cli_write failed: %s\n", nt_errstr(status));
5497                 goto out;
5498         }
5499
5500         cli_close(cli1, fnum1);
5501
5502         /* Now create a hardlink. */
5503         status = cli_posix_hardlink(cli1, fname, hname);
5504         if (!NT_STATUS_IS_OK(status)) {
5505                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5506                 goto out;
5507         }
5508
5509         /* Now create a symlink. */
5510         status = cli_posix_symlink(cli1, fname, sname);
5511         if (!NT_STATUS_IS_OK(status)) {
5512                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5513                 goto out;
5514         }
5515
5516         /* Open the hardlink for read. */
5517         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5518         if (!NT_STATUS_IS_OK(status)) {
5519                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5520                 goto out;
5521         }
5522
5523         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
5524         if (!NT_STATUS_IS_OK(status)) {
5525                 printf("POSIX read of %s failed (%s)\n", hname,
5526                        nt_errstr(status));
5527                 goto out;
5528         } else if (nread != 10) {
5529                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
5530                        hname, (unsigned long)nread, 10);
5531                 goto out;
5532         }
5533
5534         if (memcmp(buf, "TEST DATA\n", 10)) {
5535                 printf("invalid data read from hardlink\n");
5536                 goto out;
5537         }
5538
5539         /* Do a POSIX lock/unlock. */
5540         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5541         if (!NT_STATUS_IS_OK(status)) {
5542                 printf("POSIX lock failed %s\n", nt_errstr(status));
5543                 goto out;
5544         }
5545
5546         /* Punch a hole in the locked area. */
5547         status = cli_posix_unlock(cli1, fnum1, 10, 80);
5548         if (!NT_STATUS_IS_OK(status)) {
5549                 printf("POSIX unlock failed %s\n", nt_errstr(status));
5550                 goto out;
5551         }
5552
5553         cli_close(cli1, fnum1);
5554
5555         /* Open the symlink for read - this should fail. A POSIX
5556            client should not be doing opens on a symlink. */
5557         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5558         if (NT_STATUS_IS_OK(status)) {
5559                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5560                 goto out;
5561         } else {
5562                 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
5563                                 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5564                         printf("POSIX open of %s should have failed "
5565                                 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5566                                 "failed with %s instead.\n",
5567                                 sname, nt_errstr(status));
5568                         goto out;
5569                 }
5570         }
5571
5572         status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5573         if (!NT_STATUS_IS_OK(status)) {
5574                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5575                 goto out;
5576         }
5577
5578         if (strcmp(namebuf, fname) != 0) {
5579                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5580                         sname, fname, namebuf);
5581                 goto out;
5582         }
5583
5584         status = cli_posix_rmdir(cli1, dname);
5585         if (!NT_STATUS_IS_OK(status)) {
5586                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5587                 goto out;
5588         }
5589
5590         /* Check directory opens with a specific permission. */
5591         status = cli_posix_mkdir(cli1, dname, 0700);
5592         if (!NT_STATUS_IS_OK(status)) {
5593                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5594                 goto out;
5595         }
5596
5597         /* Ensure st_mode == 0700 */
5598         status = cli_posix_stat(cli1, dname, &sbuf);
5599         if (!NT_STATUS_IS_OK(status)) {
5600                 printf("stat failed (%s)\n", nt_errstr(status));
5601                 goto out;
5602         }
5603
5604         if ((sbuf.st_ex_mode & 07777) != 0700) {
5605                 printf("posix_mkdir - bad permissions 0%o != 0700\n",
5606                                 (unsigned int)(sbuf.st_ex_mode & 07777));
5607                 goto out;
5608         }
5609
5610         printf("Simple POSIX open test passed\n");
5611         correct = true;
5612
5613   out:
5614
5615         if (fnum1 != (uint16_t)-1) {
5616                 cli_close(cli1, fnum1);
5617                 fnum1 = (uint16_t)-1;
5618         }
5619
5620         cli_setatr(cli1, sname, 0, 0);
5621         cli_posix_unlink(cli1, sname);
5622         cli_setatr(cli1, hname, 0, 0);
5623         cli_posix_unlink(cli1, hname);
5624         cli_setatr(cli1, fname, 0, 0);
5625         cli_posix_unlink(cli1, fname);
5626         cli_setatr(cli1, dname, 0, 0);
5627         cli_posix_rmdir(cli1, dname);
5628
5629         if (!torture_close_connection(cli1)) {
5630                 correct = false;
5631         }
5632
5633         return correct;
5634 }
5635
5636
5637 static uint32 open_attrs_table[] = {
5638                 FILE_ATTRIBUTE_NORMAL,
5639                 FILE_ATTRIBUTE_ARCHIVE,
5640                 FILE_ATTRIBUTE_READONLY,
5641                 FILE_ATTRIBUTE_HIDDEN,
5642                 FILE_ATTRIBUTE_SYSTEM,
5643
5644                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
5645                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
5646                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
5647                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5648                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5649                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5650
5651                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5652                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5653                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5654                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
5655 };
5656
5657 struct trunc_open_results {
5658         unsigned int num;
5659         uint32 init_attr;
5660         uint32 trunc_attr;
5661         uint32 result_attr;
5662 };
5663
5664 static struct trunc_open_results attr_results[] = {
5665         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5666         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5667         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5668         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5669         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5670         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5671         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5672         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5673         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5674         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5675         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5676         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5677         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5678         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5679         { 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 },
5680         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5681         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5682         { 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 },
5683         { 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 },
5684         { 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 },
5685         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5686         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5687         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5688         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5689         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5690         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
5691 };
5692
5693 static bool run_openattrtest(int dummy)
5694 {
5695         static struct cli_state *cli1;
5696         const char *fname = "\\openattr.file";
5697         uint16_t fnum1;
5698         bool correct = True;
5699         uint16 attr;
5700         unsigned int i, j, k, l;
5701         NTSTATUS status;
5702
5703         printf("starting open attr test\n");
5704
5705         if (!torture_open_connection(&cli1, 0)) {
5706                 return False;
5707         }
5708
5709         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5710
5711         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
5712                 cli_setatr(cli1, fname, 0, 0);
5713                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5714
5715                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
5716                                        open_attrs_table[i], FILE_SHARE_NONE,
5717                                        FILE_OVERWRITE_IF, 0, 0, &fnum1);
5718                 if (!NT_STATUS_IS_OK(status)) {
5719                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5720                         return False;
5721                 }
5722
5723                 status = cli_close(cli1, fnum1);
5724                 if (!NT_STATUS_IS_OK(status)) {
5725                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5726                         return False;
5727                 }
5728
5729                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
5730                         status = cli_ntcreate(cli1, fname, 0,
5731                                               FILE_READ_DATA|FILE_WRITE_DATA,
5732                                               open_attrs_table[j],
5733                                               FILE_SHARE_NONE, FILE_OVERWRITE,
5734                                               0, 0, &fnum1);
5735                         if (!NT_STATUS_IS_OK(status)) {
5736                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5737                                         if (attr_results[l].num == k) {
5738                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
5739                                                                 k, open_attrs_table[i],
5740                                                                 open_attrs_table[j],
5741                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
5742                                                 correct = False;
5743                                         }
5744                                 }
5745
5746                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5747                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
5748                                                         k, open_attrs_table[i], open_attrs_table[j],
5749                                                         nt_errstr(status));
5750                                         correct = False;
5751                                 }
5752 #if 0
5753                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
5754 #endif
5755                                 k++;
5756                                 continue;
5757                         }
5758
5759                         status = cli_close(cli1, fnum1);
5760                         if (!NT_STATUS_IS_OK(status)) {
5761                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
5762                                 return False;
5763                         }
5764
5765                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
5766                         if (!NT_STATUS_IS_OK(status)) {
5767                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
5768                                 return False;
5769                         }
5770
5771 #if 0
5772                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
5773                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
5774 #endif
5775
5776                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5777                                 if (attr_results[l].num == k) {
5778                                         if (attr != attr_results[l].result_attr ||
5779                                                         open_attrs_table[i] != attr_results[l].init_attr ||
5780                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
5781                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
5782                                                 open_attrs_table[i],
5783                                                 open_attrs_table[j],
5784                                                 (unsigned int)attr,
5785                                                 attr_results[l].result_attr);
5786                                                 correct = False;
5787                                         }
5788                                         break;
5789                                 }
5790                         }
5791                         k++;
5792                 }
5793         }
5794
5795         cli_setatr(cli1, fname, 0, 0);
5796         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5797
5798         printf("open attr test %s.\n", correct ? "passed" : "failed");
5799
5800         if (!torture_close_connection(cli1)) {
5801                 correct = False;
5802         }
5803         return correct;
5804 }
5805
5806 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
5807                     const char *name, void *state)
5808 {
5809         int *matched = (int *)state;
5810         if (matched != NULL) {
5811                 *matched += 1;
5812         }
5813         return NT_STATUS_OK;
5814 }
5815
5816 /*
5817   test directory listing speed
5818  */
5819 static bool run_dirtest(int dummy)
5820 {
5821         int i;
5822         static struct cli_state *cli;
5823         uint16_t fnum;
5824         struct timeval core_start;
5825         bool correct = True;
5826         int matched;
5827
5828         printf("starting directory test\n");
5829
5830         if (!torture_open_connection(&cli, 0)) {
5831                 return False;
5832         }
5833
5834         smbXcli_conn_set_sockopt(cli->conn, sockops);
5835
5836         srandom(0);
5837         for (i=0;i<torture_numops;i++) {
5838                 fstring fname;
5839                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5840                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
5841                         fprintf(stderr,"Failed to open %s\n", fname);
5842                         return False;
5843                 }
5844                 cli_close(cli, fnum);
5845         }
5846
5847         core_start = timeval_current();
5848
5849         matched = 0;
5850         cli_list(cli, "a*.*", 0, list_fn, &matched);
5851         printf("Matched %d\n", matched);
5852
5853         matched = 0;
5854         cli_list(cli, "b*.*", 0, list_fn, &matched);
5855         printf("Matched %d\n", matched);
5856
5857         matched = 0;
5858         cli_list(cli, "xyzabc", 0, list_fn, &matched);
5859         printf("Matched %d\n", matched);
5860
5861         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
5862
5863         srandom(0);
5864         for (i=0;i<torture_numops;i++) {
5865                 fstring fname;
5866                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5867                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5868         }
5869
5870         if (!torture_close_connection(cli)) {
5871                 correct = False;
5872         }
5873
5874         printf("finished dirtest\n");
5875
5876         return correct;
5877 }
5878
5879 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
5880                    void *state)
5881 {
5882         struct cli_state *pcli = (struct cli_state *)state;
5883         fstring fname;
5884         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
5885
5886         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
5887                 return NT_STATUS_OK;
5888
5889         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
5890                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
5891                         printf("del_fn: failed to rmdir %s\n,", fname );
5892         } else {
5893                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
5894                         printf("del_fn: failed to unlink %s\n,", fname );
5895         }
5896         return NT_STATUS_OK;
5897 }
5898
5899
5900 /*
5901   sees what IOCTLs are supported
5902  */
5903 bool torture_ioctl_test(int dummy)
5904 {
5905         static struct cli_state *cli;
5906         uint16_t device, function;
5907         uint16_t fnum;
5908         const char *fname = "\\ioctl.dat";
5909         DATA_BLOB blob;
5910         NTSTATUS status;
5911
5912         if (!torture_open_connection(&cli, 0)) {
5913                 return False;
5914         }
5915
5916         printf("starting ioctl test\n");
5917
5918         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5919
5920         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5921         if (!NT_STATUS_IS_OK(status)) {
5922                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5923                 return False;
5924         }
5925
5926         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
5927         printf("ioctl device info: %s\n", nt_errstr(status));
5928
5929         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
5930         printf("ioctl job info: %s\n", nt_errstr(status));
5931
5932         for (device=0;device<0x100;device++) {
5933                 printf("ioctl test with device = 0x%x\n", device);
5934                 for (function=0;function<0x100;function++) {
5935                         uint32 code = (device<<16) | function;
5936
5937                         status = cli_raw_ioctl(cli, fnum, code, &blob);
5938
5939                         if (NT_STATUS_IS_OK(status)) {
5940                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
5941                                        (int)blob.length);
5942                                 data_blob_free(&blob);
5943                         }
5944                 }
5945         }
5946
5947         if (!torture_close_connection(cli)) {
5948                 return False;
5949         }
5950
5951         return True;
5952 }
5953
5954
5955 /*
5956   tries varients of chkpath
5957  */
5958 bool torture_chkpath_test(int dummy)
5959 {
5960         static struct cli_state *cli;
5961         uint16_t fnum;
5962         bool ret;
5963         NTSTATUS status;
5964
5965         if (!torture_open_connection(&cli, 0)) {
5966                 return False;
5967         }
5968
5969         printf("starting chkpath test\n");
5970
5971         /* cleanup from an old run */
5972         cli_rmdir(cli, "\\chkpath.dir\\dir2");
5973         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5974         cli_rmdir(cli, "\\chkpath.dir");
5975
5976         status = cli_mkdir(cli, "\\chkpath.dir");
5977         if (!NT_STATUS_IS_OK(status)) {
5978                 printf("mkdir1 failed : %s\n", nt_errstr(status));
5979                 return False;
5980         }
5981
5982         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
5983         if (!NT_STATUS_IS_OK(status)) {
5984                 printf("mkdir2 failed : %s\n", nt_errstr(status));
5985                 return False;
5986         }
5987
5988         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
5989                           DENY_NONE, &fnum);
5990         if (!NT_STATUS_IS_OK(status)) {
5991                 printf("open1 failed (%s)\n", nt_errstr(status));
5992                 return False;
5993         }
5994         cli_close(cli, fnum);
5995
5996         status = cli_chkpath(cli, "\\chkpath.dir");
5997         if (!NT_STATUS_IS_OK(status)) {
5998                 printf("chkpath1 failed: %s\n", nt_errstr(status));
5999                 ret = False;
6000         }
6001
6002         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
6003         if (!NT_STATUS_IS_OK(status)) {
6004                 printf("chkpath2 failed: %s\n", nt_errstr(status));
6005                 ret = False;
6006         }
6007
6008         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
6009         if (!NT_STATUS_IS_OK(status)) {
6010                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6011                                   NT_STATUS_NOT_A_DIRECTORY);
6012         } else {
6013                 printf("* chkpath on a file should fail\n");
6014                 ret = False;
6015         }
6016
6017         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
6018         if (!NT_STATUS_IS_OK(status)) {
6019                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
6020                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
6021         } else {
6022                 printf("* chkpath on a non existent file should fail\n");
6023                 ret = False;
6024         }
6025
6026         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
6027         if (!NT_STATUS_IS_OK(status)) {
6028                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6029                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
6030         } else {
6031                 printf("* chkpath on a non existent component should fail\n");
6032                 ret = False;
6033         }
6034
6035         cli_rmdir(cli, "\\chkpath.dir\\dir2");
6036         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6037         cli_rmdir(cli, "\\chkpath.dir");
6038
6039         if (!torture_close_connection(cli)) {
6040                 return False;
6041         }
6042
6043         return ret;
6044 }
6045
6046 static bool run_eatest(int dummy)
6047 {
6048         static struct cli_state *cli;
6049         const char *fname = "\\eatest.txt";
6050         bool correct = True;
6051         uint16_t fnum;
6052         int i;
6053         size_t num_eas;
6054         struct ea_struct *ea_list = NULL;
6055         TALLOC_CTX *mem_ctx = talloc_init("eatest");
6056         NTSTATUS status;
6057
6058         printf("starting eatest\n");
6059
6060         if (!torture_open_connection(&cli, 0)) {
6061                 talloc_destroy(mem_ctx);
6062                 return False;
6063         }
6064
6065         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6066
6067         status = cli_ntcreate(cli, fname, 0,
6068                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6069                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
6070                               0x4044, 0, &fnum);
6071         if (!NT_STATUS_IS_OK(status)) {
6072                 printf("open failed - %s\n", nt_errstr(status));
6073                 talloc_destroy(mem_ctx);
6074                 return False;
6075         }
6076
6077         for (i = 0; i < 10; i++) {
6078                 fstring ea_name, ea_val;
6079
6080                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
6081                 memset(ea_val, (char)i+1, i+1);
6082                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
6083                 if (!NT_STATUS_IS_OK(status)) {
6084                         printf("ea_set of name %s failed - %s\n", ea_name,
6085                                nt_errstr(status));
6086                         talloc_destroy(mem_ctx);
6087                         return False;
6088                 }
6089         }
6090
6091         cli_close(cli, fnum);
6092         for (i = 0; i < 10; i++) {
6093                 fstring ea_name, ea_val;
6094
6095                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
6096                 memset(ea_val, (char)i+1, i+1);
6097                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
6098                 if (!NT_STATUS_IS_OK(status)) {
6099                         printf("ea_set of name %s failed - %s\n", ea_name,
6100                                nt_errstr(status));
6101                         talloc_destroy(mem_ctx);
6102                         return False;
6103                 }
6104         }
6105
6106         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6107         if (!NT_STATUS_IS_OK(status)) {
6108                 printf("ea_get list failed - %s\n", nt_errstr(status));
6109                 correct = False;
6110         }
6111
6112         printf("num_eas = %d\n", (int)num_eas);
6113
6114         if (num_eas != 20) {
6115                 printf("Should be 20 EA's stored... failing.\n");
6116                 correct = False;
6117         }
6118
6119         for (i = 0; i < num_eas; i++) {
6120                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6121                 dump_data(0, ea_list[i].value.data,
6122                           ea_list[i].value.length);
6123         }
6124
6125         /* Setting EA's to zero length deletes them. Test this */
6126         printf("Now deleting all EA's - case indepenent....\n");
6127
6128 #if 1
6129         cli_set_ea_path(cli, fname, "", "", 0);
6130 #else
6131         for (i = 0; i < 20; i++) {
6132                 fstring ea_name;
6133                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
6134                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
6135                 if (!NT_STATUS_IS_OK(status)) {
6136                         printf("ea_set of name %s failed - %s\n", ea_name,
6137                                nt_errstr(status));
6138                         talloc_destroy(mem_ctx);
6139                         return False;
6140                 }
6141         }
6142 #endif
6143
6144         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6145         if (!NT_STATUS_IS_OK(status)) {
6146                 printf("ea_get list failed - %s\n", nt_errstr(status));
6147                 correct = False;
6148         }
6149
6150         printf("num_eas = %d\n", (int)num_eas);
6151         for (i = 0; i < num_eas; i++) {
6152                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6153                 dump_data(0, ea_list[i].value.data,
6154                           ea_list[i].value.length);
6155         }
6156
6157         if (num_eas != 0) {
6158                 printf("deleting EA's failed.\n");
6159                 correct = False;
6160         }
6161
6162         /* Try and delete a non existent EA. */
6163         status = cli_set_ea_path(cli, fname, "foo", "", 0);
6164         if (!NT_STATUS_IS_OK(status)) {
6165                 printf("deleting non-existent EA 'foo' should succeed. %s\n",
6166                        nt_errstr(status));
6167                 correct = False;
6168         }
6169
6170         talloc_destroy(mem_ctx);
6171         if (!torture_close_connection(cli)) {
6172                 correct = False;
6173         }
6174
6175         return correct;
6176 }
6177
6178 static bool run_dirtest1(int dummy)
6179 {
6180         int i;
6181         static struct cli_state *cli;
6182         uint16_t fnum;
6183         int num_seen;
6184         bool correct = True;
6185
6186         printf("starting directory test\n");
6187
6188         if (!torture_open_connection(&cli, 0)) {
6189                 return False;
6190         }
6191
6192         smbXcli_conn_set_sockopt(cli->conn, sockops);
6193
6194         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6195         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6196         cli_rmdir(cli, "\\LISTDIR");
6197         cli_mkdir(cli, "\\LISTDIR");
6198
6199         /* Create 1000 files and 1000 directories. */
6200         for (i=0;i<1000;i++) {
6201                 fstring fname;
6202                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
6203                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6204                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6205                         fprintf(stderr,"Failed to open %s\n", fname);
6206                         return False;
6207                 }
6208                 cli_close(cli, fnum);
6209         }
6210         for (i=0;i<1000;i++) {
6211                 fstring fname;
6212                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
6213                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
6214                         fprintf(stderr,"Failed to open %s\n", fname);
6215                         return False;
6216                 }
6217         }
6218
6219         /* Now ensure that doing an old list sees both files and directories. */
6220         num_seen = 0;
6221         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6222         printf("num_seen = %d\n", num_seen );
6223         /* We should see 100 files + 1000 directories + . and .. */
6224         if (num_seen != 2002)
6225                 correct = False;
6226
6227         /* Ensure if we have the "must have" bits we only see the
6228          * relevent entries.
6229          */
6230         num_seen = 0;
6231         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6232         printf("num_seen = %d\n", num_seen );
6233         if (num_seen != 1002)
6234                 correct = False;
6235
6236         num_seen = 0;
6237         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6238         printf("num_seen = %d\n", num_seen );
6239         if (num_seen != 1000)
6240                 correct = False;
6241
6242         /* Delete everything. */
6243         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6244         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6245         cli_rmdir(cli, "\\LISTDIR");
6246
6247 #if 0
6248         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
6249         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
6250         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
6251 #endif
6252
6253         if (!torture_close_connection(cli)) {
6254                 correct = False;
6255         }
6256
6257         printf("finished dirtest1\n");
6258
6259         return correct;
6260 }
6261
6262 static bool run_error_map_extract(int dummy) {
6263
6264         static struct cli_state *c_dos;
6265         static struct cli_state *c_nt;
6266         NTSTATUS status;
6267
6268         uint32 error;
6269
6270         uint32 errnum;
6271         uint8 errclass;
6272
6273         NTSTATUS nt_status;
6274
6275         fstring user;
6276
6277         /* NT-Error connection */
6278
6279         disable_spnego = true;
6280         if (!(c_nt = open_nbt_connection())) {
6281                 disable_spnego = false;
6282                 return False;
6283         }
6284         disable_spnego = false;
6285
6286         status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
6287                                  PROTOCOL_NT1);
6288
6289         if (!NT_STATUS_IS_OK(status)) {
6290                 printf("%s rejected the NT-error negprot (%s)\n", host,
6291                        nt_errstr(status));
6292                 cli_shutdown(c_nt);
6293                 return False;
6294         }
6295
6296         status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
6297         if (!NT_STATUS_IS_OK(status)) {
6298                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
6299                 return False;
6300         }
6301
6302         /* DOS-Error connection */
6303
6304         disable_spnego = true;
6305         force_dos_errors = true;
6306         if (!(c_dos = open_nbt_connection())) {
6307                 disable_spnego = false;
6308                 force_dos_errors = false;
6309                 return False;
6310         }
6311         disable_spnego = false;
6312         force_dos_errors = false;
6313
6314         status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
6315                                  PROTOCOL_NT1);
6316         if (!NT_STATUS_IS_OK(status)) {
6317                 printf("%s rejected the DOS-error negprot (%s)\n", host,
6318                        nt_errstr(status));
6319                 cli_shutdown(c_dos);
6320                 return False;
6321         }
6322
6323         status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
6324         if (!NT_STATUS_IS_OK(status)) {
6325                 printf("%s rejected the DOS-error initial session setup (%s)\n",
6326                         host, nt_errstr(status));
6327                 return False;
6328         }
6329
6330         c_nt->map_dos_errors = false;
6331         c_dos->map_dos_errors = false;
6332
6333         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
6334                 fstr_sprintf(user, "%X", error);
6335
6336                 status = cli_session_setup(c_nt, user,
6337                                            password, strlen(password),
6338                                            password, strlen(password),
6339                                            workgroup);
6340                 if (NT_STATUS_IS_OK(status)) {
6341                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
6342                 }
6343
6344                 /* Case #1: 32-bit NT errors */
6345                 if (!NT_STATUS_IS_DOS(status)) {
6346                         nt_status = status;
6347                 } else {
6348                         printf("/** Dos error on NT connection! (%s) */\n", 
6349                                nt_errstr(status));
6350                         nt_status = NT_STATUS(0xc0000000);
6351                 }
6352
6353                 status = cli_session_setup(c_dos, user,
6354                                            password, strlen(password),
6355                                            password, strlen(password),
6356                                            workgroup);
6357                 if (NT_STATUS_IS_OK(status)) {
6358                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
6359                 }
6360
6361                 /* Case #1: 32-bit NT errors */
6362                 if (NT_STATUS_IS_DOS(status)) {
6363                         printf("/** NT error on DOS connection! (%s) */\n", 
6364                                nt_errstr(status));
6365                         errnum = errclass = 0;
6366                 } else {
6367                         errclass = NT_STATUS_DOS_CLASS(status);
6368                         errnum = NT_STATUS_DOS_CODE(status);
6369                 }
6370
6371                 if (NT_STATUS_V(nt_status) != error) { 
6372                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
6373                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
6374                                get_nt_error_c_code(talloc_tos(), nt_status));
6375                 }
6376
6377                 printf("\t{%s,\t%s,\t%s},\n", 
6378                        smb_dos_err_class(errclass), 
6379                        smb_dos_err_name(errclass, errnum), 
6380                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
6381         }
6382         return True;
6383 }
6384
6385 static bool run_sesssetup_bench(int dummy)
6386 {
6387         static struct cli_state *c;
6388         const char *fname = "\\file.dat";
6389         uint16_t fnum;
6390         NTSTATUS status;
6391         int i;
6392
6393         if (!torture_open_connection(&c, 0)) {
6394                 return false;
6395         }
6396
6397         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6398                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6399                               FILE_DELETE_ON_CLOSE, 0, &fnum);
6400         if (!NT_STATUS_IS_OK(status)) {
6401                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6402                 return false;
6403         }
6404
6405         for (i=0; i<torture_numops; i++) {
6406                 status = cli_session_setup(
6407                         c, username,
6408                         password, strlen(password),
6409                         password, strlen(password),
6410                         workgroup);
6411                 if (!NT_STATUS_IS_OK(status)) {
6412                         d_printf("(%s) cli_session_setup failed: %s\n",
6413                                  __location__, nt_errstr(status));
6414                         return false;
6415                 }
6416
6417                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
6418
6419                 status = cli_ulogoff(c);
6420                 if (!NT_STATUS_IS_OK(status)) {
6421                         d_printf("(%s) cli_ulogoff failed: %s\n",
6422                                  __location__, nt_errstr(status));
6423                         return false;
6424                 }
6425         }
6426
6427         return true;
6428 }
6429
6430 static bool subst_test(const char *str, const char *user, const char *domain,
6431                        uid_t uid, gid_t gid, const char *expected)
6432 {
6433         char *subst;
6434         bool result = true;
6435
6436         subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
6437
6438         if (strcmp(subst, expected) != 0) {
6439                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
6440                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
6441                        expected);
6442                 result = false;
6443         }
6444
6445         TALLOC_FREE(subst);
6446         return result;
6447 }
6448
6449 static void chain1_open_completion(struct tevent_req *req)
6450 {
6451         uint16_t fnum;
6452         NTSTATUS status;
6453         status = cli_openx_recv(req, &fnum);
6454         TALLOC_FREE(req);
6455
6456         d_printf("cli_openx_recv returned %s: %d\n",
6457                  nt_errstr(status),
6458                  NT_STATUS_IS_OK(status) ? fnum : -1);
6459 }
6460
6461 static void chain1_write_completion(struct tevent_req *req)
6462 {
6463         size_t written;
6464         NTSTATUS status;
6465         status = cli_write_andx_recv(req, &written);
6466         TALLOC_FREE(req);
6467
6468         d_printf("cli_write_andx_recv returned %s: %d\n",
6469                  nt_errstr(status),
6470                  NT_STATUS_IS_OK(status) ? (int)written : -1);
6471 }
6472
6473 static void chain1_close_completion(struct tevent_req *req)
6474 {
6475         NTSTATUS status;
6476         bool *done = (bool *)tevent_req_callback_data_void(req);
6477
6478         status = cli_close_recv(req);
6479         *done = true;
6480
6481         TALLOC_FREE(req);
6482
6483         d_printf("cli_close returned %s\n", nt_errstr(status));
6484 }
6485
6486 static bool run_chain1(int dummy)
6487 {
6488         struct cli_state *cli1;
6489         struct event_context *evt = event_context_init(NULL);
6490         struct tevent_req *reqs[3], *smbreqs[3];
6491         bool done = false;
6492         const char *str = "foobar";
6493         NTSTATUS status;
6494
6495         printf("starting chain1 test\n");
6496         if (!torture_open_connection(&cli1, 0)) {
6497                 return False;
6498         }
6499
6500         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6501
6502         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, "\\test",
6503                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
6504         if (reqs[0] == NULL) return false;
6505         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
6506
6507
6508         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
6509                                         (const uint8_t *)str, 0, strlen(str)+1,
6510                                         smbreqs, 1, &smbreqs[1]);
6511         if (reqs[1] == NULL) return false;
6512         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
6513
6514         reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
6515         if (reqs[2] == NULL) return false;
6516         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
6517
6518         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
6519         if (!NT_STATUS_IS_OK(status)) {
6520                 return false;
6521         }
6522
6523         while (!done) {
6524                 tevent_loop_once(evt);
6525         }
6526
6527         torture_close_connection(cli1);
6528         return True;
6529 }
6530
6531 static void chain2_sesssetup_completion(struct tevent_req *req)
6532 {
6533         NTSTATUS status;
6534         status = cli_session_setup_guest_recv(req);
6535         d_printf("sesssetup returned %s\n", nt_errstr(status));
6536 }
6537
6538 static void chain2_tcon_completion(struct tevent_req *req)
6539 {
6540         bool *done = (bool *)tevent_req_callback_data_void(req);
6541         NTSTATUS status;
6542         status = cli_tcon_andx_recv(req);
6543         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
6544         *done = true;
6545 }
6546
6547 static bool run_chain2(int dummy)
6548 {
6549         struct cli_state *cli1;
6550         struct event_context *evt = event_context_init(NULL);
6551         struct tevent_req *reqs[2], *smbreqs[2];
6552         bool done = false;
6553         NTSTATUS status;
6554
6555         printf("starting chain2 test\n");
6556         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
6557                                       port_to_use, SMB_SIGNING_DEFAULT, 0);
6558         if (!NT_STATUS_IS_OK(status)) {
6559                 return False;
6560         }
6561
6562         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6563
6564         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
6565                                                  &smbreqs[0]);
6566         if (reqs[0] == NULL) return false;
6567         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
6568
6569         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
6570                                        "?????", NULL, 0, &smbreqs[1]);
6571         if (reqs[1] == NULL) return false;
6572         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
6573
6574         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
6575         if (!NT_STATUS_IS_OK(status)) {
6576                 return false;
6577         }
6578
6579         while (!done) {
6580                 tevent_loop_once(evt);
6581         }
6582
6583         torture_close_connection(cli1);
6584         return True;
6585 }
6586
6587
6588 struct torture_createdel_state {
6589         struct tevent_context *ev;
6590         struct cli_state *cli;
6591 };
6592
6593 static void torture_createdel_created(struct tevent_req *subreq);
6594 static void torture_createdel_closed(struct tevent_req *subreq);
6595
6596 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
6597                                                  struct tevent_context *ev,
6598                                                  struct cli_state *cli,
6599                                                  const char *name)
6600 {
6601         struct tevent_req *req, *subreq;
6602         struct torture_createdel_state *state;
6603
6604         req = tevent_req_create(mem_ctx, &state,
6605                                 struct torture_createdel_state);
6606         if (req == NULL) {
6607                 return NULL;
6608         }
6609         state->ev = ev;
6610         state->cli = cli;
6611
6612         subreq = cli_ntcreate_send(
6613                 state, ev, cli, name, 0,
6614                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
6615                 FILE_ATTRIBUTE_NORMAL,
6616                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6617                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
6618
6619         if (tevent_req_nomem(subreq, req)) {
6620                 return tevent_req_post(req, ev);
6621         }
6622         tevent_req_set_callback(subreq, torture_createdel_created, req);
6623         return req;
6624 }
6625
6626 static void torture_createdel_created(struct tevent_req *subreq)
6627 {
6628         struct tevent_req *req = tevent_req_callback_data(
6629                 subreq, struct tevent_req);
6630         struct torture_createdel_state *state = tevent_req_data(
6631                 req, struct torture_createdel_state);
6632         NTSTATUS status;
6633         uint16_t fnum;
6634
6635         status = cli_ntcreate_recv(subreq, &fnum);
6636         TALLOC_FREE(subreq);
6637         if (!NT_STATUS_IS_OK(status)) {
6638                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
6639                            nt_errstr(status)));
6640                 tevent_req_nterror(req, status);
6641                 return;
6642         }
6643
6644         subreq = cli_close_send(state, state->ev, state->cli, fnum);
6645         if (tevent_req_nomem(subreq, req)) {
6646                 return;
6647         }
6648         tevent_req_set_callback(subreq, torture_createdel_closed, req);
6649 }
6650
6651 static void torture_createdel_closed(struct tevent_req *subreq)
6652 {
6653         struct tevent_req *req = tevent_req_callback_data(
6654                 subreq, struct tevent_req);
6655         NTSTATUS status;
6656
6657         status = cli_close_recv(subreq);
6658         if (!NT_STATUS_IS_OK(status)) {
6659                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
6660                 tevent_req_nterror(req, status);
6661                 return;
6662         }
6663         tevent_req_done(req);
6664 }
6665
6666 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
6667 {
6668         return tevent_req_simple_recv_ntstatus(req);
6669 }
6670
6671 struct torture_createdels_state {
6672         struct tevent_context *ev;
6673         struct cli_state *cli;
6674         const char *base_name;
6675         int sent;
6676         int received;
6677         int num_files;
6678         struct tevent_req **reqs;
6679 };
6680
6681 static void torture_createdels_done(struct tevent_req *subreq);
6682
6683 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
6684                                                   struct tevent_context *ev,
6685                                                   struct cli_state *cli,
6686                                                   const char *base_name,
6687                                                   int num_parallel,
6688                                                   int num_files)
6689 {
6690         struct tevent_req *req;
6691         struct torture_createdels_state *state;
6692         int i;
6693
6694         req = tevent_req_create(mem_ctx, &state,
6695                                 struct torture_createdels_state);
6696         if (req == NULL) {
6697                 return NULL;
6698         }
6699         state->ev = ev;
6700         state->cli = cli;
6701         state->base_name = talloc_strdup(state, base_name);
6702         if (tevent_req_nomem(state->base_name, req)) {
6703                 return tevent_req_post(req, ev);
6704         }
6705         state->num_files = MAX(num_parallel, num_files);
6706         state->sent = 0;
6707         state->received = 0;
6708
6709         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
6710         if (tevent_req_nomem(state->reqs, req)) {
6711                 return tevent_req_post(req, ev);
6712         }
6713
6714         for (i=0; i<num_parallel; i++) {
6715                 char *name;
6716
6717                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6718                                        state->sent);
6719                 if (tevent_req_nomem(name, req)) {
6720                         return tevent_req_post(req, ev);
6721                 }
6722                 state->reqs[i] = torture_createdel_send(
6723                         state->reqs, state->ev, state->cli, name);
6724                 if (tevent_req_nomem(state->reqs[i], req)) {
6725                         return tevent_req_post(req, ev);
6726                 }
6727                 name = talloc_move(state->reqs[i], &name);
6728                 tevent_req_set_callback(state->reqs[i],
6729                                         torture_createdels_done, req);
6730                 state->sent += 1;
6731         }
6732         return req;
6733 }
6734
6735 static void torture_createdels_done(struct tevent_req *subreq)
6736 {
6737         struct tevent_req *req = tevent_req_callback_data(
6738                 subreq, struct tevent_req);
6739         struct torture_createdels_state *state = tevent_req_data(
6740                 req, struct torture_createdels_state);
6741         size_t num_parallel = talloc_array_length(state->reqs);
6742         NTSTATUS status;
6743         char *name;
6744         int i;
6745
6746         status = torture_createdel_recv(subreq);
6747         if (!NT_STATUS_IS_OK(status)){
6748                 DEBUG(10, ("torture_createdel_recv returned %s\n",
6749                            nt_errstr(status)));
6750                 TALLOC_FREE(subreq);
6751                 tevent_req_nterror(req, status);
6752                 return;
6753         }
6754
6755         for (i=0; i<num_parallel; i++) {
6756                 if (subreq == state->reqs[i]) {
6757                         break;
6758                 }
6759         }
6760         if (i == num_parallel) {
6761                 DEBUG(10, ("received something we did not send\n"));
6762                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
6763                 return;
6764         }
6765         TALLOC_FREE(state->reqs[i]);
6766
6767         if (state->sent >= state->num_files) {
6768                 tevent_req_done(req);
6769                 return;
6770         }
6771
6772         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6773                                state->sent);
6774         if (tevent_req_nomem(name, req)) {
6775                 return;
6776         }
6777         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
6778                                                 state->cli, name);
6779         if (tevent_req_nomem(state->reqs[i], req)) {
6780                 return;
6781         }
6782         name = talloc_move(state->reqs[i], &name);
6783         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
6784         state->sent += 1;
6785 }
6786
6787 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
6788 {
6789         return tevent_req_simple_recv_ntstatus(req);
6790 }
6791
6792 struct swallow_notify_state {
6793         struct tevent_context *ev;
6794         struct cli_state *cli;
6795         uint16_t fnum;
6796         uint32_t completion_filter;
6797         bool recursive;
6798         bool (*fn)(uint32_t action, const char *name, void *priv);
6799         void *priv;
6800 };
6801
6802 static void swallow_notify_done(struct tevent_req *subreq);
6803
6804 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
6805                                               struct tevent_context *ev,
6806                                               struct cli_state *cli,
6807                                               uint16_t fnum,
6808                                               uint32_t completion_filter,
6809                                               bool recursive,
6810                                               bool (*fn)(uint32_t action,
6811                                                          const char *name,
6812                                                          void *priv),
6813                                               void *priv)
6814 {
6815         struct tevent_req *req, *subreq;
6816         struct swallow_notify_state *state;
6817
6818         req = tevent_req_create(mem_ctx, &state,
6819                                 struct swallow_notify_state);
6820         if (req == NULL) {
6821                 return NULL;
6822         }
6823         state->ev = ev;
6824         state->cli = cli;
6825         state->fnum = fnum;
6826         state->completion_filter = completion_filter;
6827         state->recursive = recursive;
6828         state->fn = fn;
6829         state->priv = priv;
6830
6831         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6832                                  0xffff, state->completion_filter,
6833                                  state->recursive);
6834         if (tevent_req_nomem(subreq, req)) {
6835                 return tevent_req_post(req, ev);
6836         }
6837         tevent_req_set_callback(subreq, swallow_notify_done, req);
6838         return req;
6839 }
6840
6841 static void swallow_notify_done(struct tevent_req *subreq)
6842 {
6843         struct tevent_req *req = tevent_req_callback_data(
6844                 subreq, struct tevent_req);
6845         struct swallow_notify_state *state = tevent_req_data(
6846                 req, struct swallow_notify_state);
6847         NTSTATUS status;
6848         uint32_t i, num_changes;
6849         struct notify_change *changes;
6850
6851         status = cli_notify_recv(subreq, state, &num_changes, &changes);
6852         TALLOC_FREE(subreq);
6853         if (!NT_STATUS_IS_OK(status)) {
6854                 DEBUG(10, ("cli_notify_recv returned %s\n",
6855                            nt_errstr(status)));
6856                 tevent_req_nterror(req, status);
6857                 return;
6858         }
6859
6860         for (i=0; i<num_changes; i++) {
6861                 state->fn(changes[i].action, changes[i].name, state->priv);
6862         }
6863         TALLOC_FREE(changes);
6864
6865         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6866                                  0xffff, state->completion_filter,
6867                                  state->recursive);
6868         if (tevent_req_nomem(subreq, req)) {
6869                 return;
6870         }
6871         tevent_req_set_callback(subreq, swallow_notify_done, req);
6872 }
6873
6874 static bool print_notifies(uint32_t action, const char *name, void *priv)
6875 {
6876         if (DEBUGLEVEL > 5) {
6877                 d_printf("%d %s\n", (int)action, name);
6878         }
6879         return true;
6880 }
6881
6882 static void notify_bench_done(struct tevent_req *req)
6883 {
6884         int *num_finished = (int *)tevent_req_callback_data_void(req);
6885         *num_finished += 1;
6886 }
6887
6888 static bool run_notify_bench(int dummy)
6889 {
6890         const char *dname = "\\notify-bench";
6891         struct tevent_context *ev;
6892         NTSTATUS status;
6893         uint16_t dnum;
6894         struct tevent_req *req1;
6895         struct tevent_req *req2 = NULL;
6896         int i, num_unc_names;
6897         int num_finished = 0;
6898
6899         printf("starting notify-bench test\n");
6900
6901         if (use_multishare_conn) {
6902                 char **unc_list;
6903                 unc_list = file_lines_load(multishare_conn_fname,
6904                                            &num_unc_names, 0, NULL);
6905                 if (!unc_list || num_unc_names <= 0) {
6906                         d_printf("Failed to load unc names list from '%s'\n",
6907                                  multishare_conn_fname);
6908                         return false;
6909                 }
6910                 TALLOC_FREE(unc_list);
6911         } else {
6912                 num_unc_names = 1;
6913         }
6914
6915         ev = tevent_context_init(talloc_tos());
6916         if (ev == NULL) {
6917                 d_printf("tevent_context_init failed\n");
6918                 return false;
6919         }
6920
6921         for (i=0; i<num_unc_names; i++) {
6922                 struct cli_state *cli;
6923                 char *base_fname;
6924
6925                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
6926                                              dname, i);
6927                 if (base_fname == NULL) {
6928                         return false;
6929                 }
6930
6931                 if (!torture_open_connection(&cli, i)) {
6932                         return false;
6933                 }
6934
6935                 status = cli_ntcreate(cli, dname, 0,
6936                                       MAXIMUM_ALLOWED_ACCESS,
6937                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
6938                                       FILE_SHARE_DELETE,
6939                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
6940                                       &dnum);
6941
6942                 if (!NT_STATUS_IS_OK(status)) {
6943                         d_printf("Could not create %s: %s\n", dname,
6944                                  nt_errstr(status));
6945                         return false;
6946                 }
6947
6948                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
6949                                            FILE_NOTIFY_CHANGE_FILE_NAME |
6950                                            FILE_NOTIFY_CHANGE_DIR_NAME |
6951                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
6952                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
6953                                            false, print_notifies, NULL);
6954                 if (req1 == NULL) {
6955                         d_printf("Could not create notify request\n");
6956                         return false;
6957                 }
6958
6959                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
6960                                                base_fname, 10, torture_numops);
6961                 if (req2 == NULL) {
6962                         d_printf("Could not create createdels request\n");
6963                         return false;
6964                 }
6965                 TALLOC_FREE(base_fname);
6966
6967                 tevent_req_set_callback(req2, notify_bench_done,
6968                                         &num_finished);
6969         }
6970
6971         while (num_finished < num_unc_names) {
6972                 int ret;
6973                 ret = tevent_loop_once(ev);
6974                 if (ret != 0) {
6975                         d_printf("tevent_loop_once failed\n");
6976                         return false;
6977                 }
6978         }
6979
6980         if (!tevent_req_poll(req2, ev)) {
6981                 d_printf("tevent_req_poll failed\n");
6982         }
6983
6984         status = torture_createdels_recv(req2);
6985         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
6986
6987         return true;
6988 }
6989
6990 static bool run_mangle1(int dummy)
6991 {
6992         struct cli_state *cli;
6993         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
6994         uint16_t fnum;
6995         fstring alt_name;
6996         NTSTATUS status;
6997         time_t change_time, access_time, write_time;
6998         off_t size;
6999         uint16_t mode;
7000
7001         printf("starting mangle1 test\n");
7002         if (!torture_open_connection(&cli, 0)) {
7003                 return False;
7004         }
7005
7006         smbXcli_conn_set_sockopt(cli->conn, sockops);
7007
7008         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7009                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7010                               0, 0, &fnum);
7011         if (!NT_STATUS_IS_OK(status)) {
7012                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7013                 return false;
7014         }
7015         cli_close(cli, fnum);
7016
7017         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
7018         if (!NT_STATUS_IS_OK(status)) {
7019                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
7020                          nt_errstr(status));
7021                 return false;
7022         }
7023         d_printf("alt_name: %s\n", alt_name);
7024
7025         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
7026         if (!NT_STATUS_IS_OK(status)) {
7027                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
7028                          nt_errstr(status));
7029                 return false;
7030         }
7031         cli_close(cli, fnum);
7032
7033         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
7034                                 &write_time, &size, &mode);
7035         if (!NT_STATUS_IS_OK(status)) {
7036                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
7037                          nt_errstr(status));
7038                 return false;
7039         }
7040
7041         return true;
7042 }
7043
7044 static size_t null_source(uint8_t *buf, size_t n, void *priv)
7045 {
7046         size_t *to_pull = (size_t *)priv;
7047         size_t thistime = *to_pull;
7048
7049         thistime = MIN(thistime, n);
7050         if (thistime == 0) {
7051                 return 0;
7052         }
7053
7054         memset(buf, 0, thistime);
7055         *to_pull -= thistime;
7056         return thistime;
7057 }
7058
7059 static bool run_windows_write(int dummy)
7060 {
7061         struct cli_state *cli1;
7062         uint16_t fnum;
7063         int i;
7064         bool ret = false;
7065         const char *fname = "\\writetest.txt";
7066         struct timeval start_time;
7067         double seconds;
7068         double kbytes;
7069         NTSTATUS status;
7070
7071         printf("starting windows_write test\n");
7072         if (!torture_open_connection(&cli1, 0)) {
7073                 return False;
7074         }
7075
7076         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7077         if (!NT_STATUS_IS_OK(status)) {
7078                 printf("open failed (%s)\n", nt_errstr(status));
7079                 return False;
7080         }
7081
7082         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7083
7084         start_time = timeval_current();
7085
7086         for (i=0; i<torture_numops; i++) {
7087                 uint8_t c = 0;
7088                 off_t start = i * torture_blocksize;
7089                 size_t to_pull = torture_blocksize - 1;
7090
7091                 status = cli_writeall(cli1, fnum, 0, &c,
7092                                       start + torture_blocksize - 1, 1, NULL);
7093                 if (!NT_STATUS_IS_OK(status)) {
7094                         printf("cli_write failed: %s\n", nt_errstr(status));
7095                         goto fail;
7096                 }
7097
7098                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
7099                                   null_source, &to_pull);
7100                 if (!NT_STATUS_IS_OK(status)) {
7101                         printf("cli_push returned: %s\n", nt_errstr(status));
7102                         goto fail;
7103                 }
7104         }
7105
7106         seconds = timeval_elapsed(&start_time);
7107         kbytes = (double)torture_blocksize * torture_numops;
7108         kbytes /= 1024;
7109
7110         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
7111                (double)seconds, (int)(kbytes/seconds));
7112
7113         ret = true;
7114  fail:
7115         cli_close(cli1, fnum);
7116         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7117         torture_close_connection(cli1);
7118         return ret;
7119 }
7120
7121 static bool run_cli_echo(int dummy)
7122 {
7123         struct cli_state *cli;
7124         NTSTATUS status;
7125
7126         printf("starting cli_echo test\n");
7127         if (!torture_open_connection(&cli, 0)) {
7128                 return false;
7129         }
7130         smbXcli_conn_set_sockopt(cli->conn, sockops);
7131
7132         status = cli_echo(cli, 5, data_blob_const("hello", 5));
7133
7134         d_printf("cli_echo returned %s\n", nt_errstr(status));
7135
7136         torture_close_connection(cli);
7137         return NT_STATUS_IS_OK(status);
7138 }
7139
7140 static bool run_uid_regression_test(int dummy)
7141 {
7142         static struct cli_state *cli;
7143         int16_t old_vuid;
7144         int16_t old_cnum;
7145         bool correct = True;
7146         NTSTATUS status;
7147
7148         printf("starting uid regression test\n");
7149
7150         if (!torture_open_connection(&cli, 0)) {
7151                 return False;
7152         }
7153
7154         smbXcli_conn_set_sockopt(cli->conn, sockops);
7155
7156         /* Ok - now save then logoff our current user. */
7157         old_vuid = cli_state_get_uid(cli);
7158
7159         status = cli_ulogoff(cli);
7160         if (!NT_STATUS_IS_OK(status)) {
7161                 d_printf("(%s) cli_ulogoff failed: %s\n",
7162                          __location__, nt_errstr(status));
7163                 correct = false;
7164                 goto out;
7165         }
7166
7167         cli_state_set_uid(cli, old_vuid);
7168
7169         /* Try an operation. */
7170         status = cli_mkdir(cli, "\\uid_reg_test");
7171         if (NT_STATUS_IS_OK(status)) {
7172                 d_printf("(%s) cli_mkdir succeeded\n",
7173                          __location__);
7174                 correct = false;
7175                 goto out;
7176         } else {
7177                 /* Should be bad uid. */
7178                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
7179                                  NT_STATUS_USER_SESSION_DELETED)) {
7180                         correct = false;
7181                         goto out;
7182                 }
7183         }
7184
7185         old_cnum = cli_state_get_tid(cli);
7186
7187         /* Now try a SMBtdis with the invald vuid set to zero. */
7188         cli_state_set_uid(cli, 0);
7189
7190         /* This should succeed. */
7191         status = cli_tdis(cli);
7192
7193         if (NT_STATUS_IS_OK(status)) {
7194                 d_printf("First tdis with invalid vuid should succeed.\n");
7195         } else {
7196                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
7197                 correct = false;
7198                 goto out;
7199         }
7200
7201         cli_state_set_uid(cli, old_vuid);
7202         cli_state_set_tid(cli, old_cnum);
7203
7204         /* This should fail. */
7205         status = cli_tdis(cli);
7206         if (NT_STATUS_IS_OK(status)) {
7207                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
7208                 correct = false;
7209                 goto out;
7210         } else {
7211                 /* Should be bad tid. */
7212                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
7213                                 NT_STATUS_NETWORK_NAME_DELETED)) {
7214                         correct = false;
7215                         goto out;
7216                 }
7217         }
7218
7219         cli_rmdir(cli, "\\uid_reg_test");
7220
7221   out:
7222
7223         cli_shutdown(cli);
7224         return correct;
7225 }
7226
7227
7228 static const char *illegal_chars = "*\\/?<>|\":";
7229 static char force_shortname_chars[] = " +,.[];=\177";
7230
7231 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
7232                              const char *mask, void *state)
7233 {
7234         struct cli_state *pcli = (struct cli_state *)state;
7235         fstring fname;
7236         NTSTATUS status = NT_STATUS_OK;
7237
7238         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
7239
7240         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7241                 return NT_STATUS_OK;
7242
7243         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7244                 status = cli_rmdir(pcli, fname);
7245                 if (!NT_STATUS_IS_OK(status)) {
7246                         printf("del_fn: failed to rmdir %s\n,", fname );
7247                 }
7248         } else {
7249                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7250                 if (!NT_STATUS_IS_OK(status)) {
7251                         printf("del_fn: failed to unlink %s\n,", fname );
7252                 }
7253         }
7254         return status;
7255 }
7256
7257 struct sn_state {
7258         int matched;
7259         int i;
7260         bool val;
7261 };
7262
7263 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
7264                               const char *name, void *state)
7265 {
7266         struct sn_state *s = (struct sn_state  *)state;
7267         int i = s->i;
7268
7269 #if 0
7270         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
7271                 i, finfo->name, finfo->short_name);
7272 #endif
7273
7274         if (strchr(force_shortname_chars, i)) {
7275                 if (!finfo->short_name) {
7276                         /* Shortname not created when it should be. */
7277                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
7278                                 __location__, finfo->name, i);
7279                         s->val = true;
7280                 }
7281         } else if (finfo->short_name){
7282                 /* Shortname created when it should not be. */
7283                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
7284                         __location__, finfo->short_name, finfo->name);
7285                 s->val = true;
7286         }
7287         s->matched += 1;
7288         return NT_STATUS_OK;
7289 }
7290
7291 static bool run_shortname_test(int dummy)
7292 {
7293         static struct cli_state *cli;
7294         bool correct = True;
7295         int i;
7296         struct sn_state s;
7297         char fname[40];
7298         NTSTATUS status;
7299
7300         printf("starting shortname test\n");
7301
7302         if (!torture_open_connection(&cli, 0)) {
7303                 return False;
7304         }
7305
7306         smbXcli_conn_set_sockopt(cli->conn, sockops);
7307
7308         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7309         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7310         cli_rmdir(cli, "\\shortname");
7311
7312         status = cli_mkdir(cli, "\\shortname");
7313         if (!NT_STATUS_IS_OK(status)) {
7314                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
7315                         __location__, nt_errstr(status));
7316                 correct = false;
7317                 goto out;
7318         }
7319
7320         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
7321                 correct = false;
7322                 goto out;
7323         }
7324         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
7325                 correct = false;
7326                 goto out;
7327         }
7328
7329         s.val = false;
7330
7331         for (i = 32; i < 128; i++) {
7332                 uint16_t fnum = (uint16_t)-1;
7333
7334                 s.i = i;
7335
7336                 if (strchr(illegal_chars, i)) {
7337                         continue;
7338                 }
7339                 fname[15] = i;
7340
7341                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
7342                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
7343                 if (!NT_STATUS_IS_OK(status)) {
7344                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
7345                                 __location__, fname, nt_errstr(status));
7346                         correct = false;
7347                         goto out;
7348                 }
7349                 cli_close(cli, fnum);
7350
7351                 s.matched = 0;
7352                 status = cli_list(cli, "\\shortname\\test*.*", 0,
7353                                   shortname_list_fn, &s);
7354                 if (s.matched != 1) {
7355                         d_printf("(%s) failed to list %s: %s\n",
7356                                 __location__, fname, nt_errstr(status));
7357                         correct = false;
7358                         goto out;
7359                 }
7360
7361                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7362                 if (!NT_STATUS_IS_OK(status)) {
7363                         d_printf("(%s) failed to delete %s: %s\n",
7364                                 __location__, fname, nt_errstr(status));
7365                         correct = false;
7366                         goto out;
7367                 }
7368
7369                 if (s.val) {
7370                         correct = false;
7371                         goto out;
7372                 }
7373         }
7374
7375   out:
7376
7377         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7378         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7379         cli_rmdir(cli, "\\shortname");
7380         torture_close_connection(cli);
7381         return correct;
7382 }
7383
7384 static void pagedsearch_cb(struct tevent_req *req)
7385 {
7386         int rc;
7387         struct tldap_message *msg;
7388         char *dn;
7389
7390         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
7391         if (rc != TLDAP_SUCCESS) {
7392                 d_printf("tldap_search_paged_recv failed: %s\n",
7393                          tldap_err2string(rc));
7394                 return;
7395         }
7396         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
7397                 TALLOC_FREE(msg);
7398                 return;
7399         }
7400         if (!tldap_entry_dn(msg, &dn)) {
7401                 d_printf("tldap_entry_dn failed\n");
7402                 return;
7403         }
7404         d_printf("%s\n", dn);
7405         TALLOC_FREE(msg);
7406 }
7407
7408 static bool run_tldap(int dummy)
7409 {
7410         struct tldap_context *ld;
7411         int fd, rc;
7412         NTSTATUS status;
7413         struct sockaddr_storage addr;
7414         struct tevent_context *ev;
7415         struct tevent_req *req;
7416         char *basedn;
7417         const char *filter;
7418
7419         if (!resolve_name(host, &addr, 0, false)) {
7420                 d_printf("could not find host %s\n", host);
7421                 return false;
7422         }
7423         status = open_socket_out(&addr, 389, 9999, &fd);
7424         if (!NT_STATUS_IS_OK(status)) {
7425                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
7426                 return false;
7427         }
7428
7429         ld = tldap_context_create(talloc_tos(), fd);
7430         if (ld == NULL) {
7431                 close(fd);
7432                 d_printf("tldap_context_create failed\n");
7433                 return false;
7434         }
7435
7436         rc = tldap_fetch_rootdse(ld);
7437         if (rc != TLDAP_SUCCESS) {
7438                 d_printf("tldap_fetch_rootdse failed: %s\n",
7439                          tldap_errstr(talloc_tos(), ld, rc));
7440                 return false;
7441         }
7442
7443         basedn = tldap_talloc_single_attribute(
7444                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
7445         if (basedn == NULL) {
7446                 d_printf("no defaultNamingContext\n");
7447                 return false;
7448         }
7449         d_printf("defaultNamingContext: %s\n", basedn);
7450
7451         ev = tevent_context_init(talloc_tos());
7452         if (ev == NULL) {
7453                 d_printf("tevent_context_init failed\n");
7454                 return false;
7455         }
7456
7457         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
7458                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
7459                                       NULL, 0, 0,
7460                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
7461         if (req == NULL) {
7462                 d_printf("tldap_search_paged_send failed\n");
7463                 return false;
7464         }
7465         tevent_req_set_callback(req, pagedsearch_cb, NULL);
7466
7467         tevent_req_poll(req, ev);
7468
7469         TALLOC_FREE(req);
7470
7471         /* test search filters against rootDSE */
7472         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
7473                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
7474
7475         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
7476                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
7477                           talloc_tos(), NULL, NULL);
7478         if (rc != TLDAP_SUCCESS) {
7479                 d_printf("tldap_search with complex filter failed: %s\n",
7480                          tldap_errstr(talloc_tos(), ld, rc));
7481                 return false;
7482         }
7483
7484         TALLOC_FREE(ld);
7485         return true;
7486 }
7487
7488 /* Torture test to ensure no regression of :
7489 https://bugzilla.samba.org/show_bug.cgi?id=7084
7490 */
7491
7492 static bool run_dir_createtime(int dummy)
7493 {
7494         struct cli_state *cli;
7495         const char *dname = "\\testdir";
7496         const char *fname = "\\testdir\\testfile";
7497         NTSTATUS status;
7498         struct timespec create_time;
7499         struct timespec create_time1;
7500         uint16_t fnum;
7501         bool ret = false;
7502
7503         if (!torture_open_connection(&cli, 0)) {
7504                 return false;
7505         }
7506
7507         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7508         cli_rmdir(cli, dname);
7509
7510         status = cli_mkdir(cli, dname);
7511         if (!NT_STATUS_IS_OK(status)) {
7512                 printf("mkdir failed: %s\n", nt_errstr(status));
7513                 goto out;
7514         }
7515
7516         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
7517                                 NULL, NULL, NULL);
7518         if (!NT_STATUS_IS_OK(status)) {
7519                 printf("cli_qpathinfo2 returned %s\n",
7520                        nt_errstr(status));
7521                 goto out;
7522         }
7523
7524         /* Sleep 3 seconds, then create a file. */
7525         sleep(3);
7526
7527         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
7528                          DENY_NONE, &fnum);
7529         if (!NT_STATUS_IS_OK(status)) {
7530                 printf("cli_openx failed: %s\n", nt_errstr(status));
7531                 goto out;
7532         }
7533
7534         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
7535                                 NULL, NULL, NULL);
7536         if (!NT_STATUS_IS_OK(status)) {
7537                 printf("cli_qpathinfo2 (2) returned %s\n",
7538                        nt_errstr(status));
7539                 goto out;
7540         }
7541
7542         if (timespec_compare(&create_time1, &create_time)) {
7543                 printf("run_dir_createtime: create time was updated (error)\n");
7544         } else {
7545                 printf("run_dir_createtime: create time was not updated (correct)\n");
7546                 ret = true;
7547         }
7548
7549   out:
7550
7551         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7552         cli_rmdir(cli, dname);
7553         if (!torture_close_connection(cli)) {
7554                 ret = false;
7555         }
7556         return ret;
7557 }
7558
7559
7560 static bool run_streamerror(int dummy)
7561 {
7562         struct cli_state *cli;
7563         const char *dname = "\\testdir";
7564         const char *streamname =
7565                 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
7566         NTSTATUS status;
7567         time_t change_time, access_time, write_time;
7568         off_t size;
7569         uint16_t mode, fnum;
7570         bool ret = true;
7571
7572         if (!torture_open_connection(&cli, 0)) {
7573                 return false;
7574         }
7575
7576         cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7577         cli_rmdir(cli, dname);
7578
7579         status = cli_mkdir(cli, dname);
7580         if (!NT_STATUS_IS_OK(status)) {
7581                 printf("mkdir failed: %s\n", nt_errstr(status));
7582                 return false;
7583         }
7584
7585         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
7586                                 &write_time, &size, &mode);
7587         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7588                 printf("pathinfo returned %s, expected "
7589                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7590                        nt_errstr(status));
7591                 ret = false;
7592         }
7593
7594         status = cli_ntcreate(cli, streamname, 0x16,
7595                               FILE_READ_DATA|FILE_READ_EA|
7596                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
7597                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7598                               FILE_OPEN, 0, 0, &fnum);
7599
7600         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7601                 printf("ntcreate returned %s, expected "
7602                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7603                        nt_errstr(status));
7604                 ret = false;
7605         }
7606
7607
7608         cli_rmdir(cli, dname);
7609         return ret;
7610 }
7611
7612 static bool run_local_substitute(int dummy)
7613 {
7614         bool ok = true;
7615
7616         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
7617         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
7618         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
7619         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
7620         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
7621         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
7622         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
7623         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
7624
7625         /* Different captialization rules in sub_basic... */
7626
7627         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
7628                        "blaDOM") == 0);
7629
7630         return ok;
7631 }
7632
7633 static bool run_local_base64(int dummy)
7634 {
7635         int i;
7636         bool ret = true;
7637
7638         for (i=1; i<2000; i++) {
7639                 DATA_BLOB blob1, blob2;
7640                 char *b64;
7641
7642                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
7643                 blob1.length = i;
7644                 generate_random_buffer(blob1.data, blob1.length);
7645
7646                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
7647                 if (b64 == NULL) {
7648                         d_fprintf(stderr, "base64_encode_data_blob failed "
7649                                   "for %d bytes\n", i);
7650                         ret = false;
7651                 }
7652                 blob2 = base64_decode_data_blob(b64);
7653                 TALLOC_FREE(b64);
7654
7655                 if (data_blob_cmp(&blob1, &blob2)) {
7656                         d_fprintf(stderr, "data_blob_cmp failed for %d "
7657                                   "bytes\n", i);
7658                         ret = false;
7659                 }
7660                 TALLOC_FREE(blob1.data);
7661                 data_blob_free(&blob2);
7662         }
7663         return ret;
7664 }
7665
7666 static bool run_local_gencache(int dummy)
7667 {
7668         char *val;
7669         time_t tm;
7670         DATA_BLOB blob;
7671
7672         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
7673                 d_printf("%s: gencache_set() failed\n", __location__);
7674                 return False;
7675         }
7676
7677         if (!gencache_get("foo", NULL, NULL)) {
7678                 d_printf("%s: gencache_get() failed\n", __location__);
7679                 return False;
7680         }
7681
7682         if (!gencache_get("foo", &val, &tm)) {
7683                 d_printf("%s: gencache_get() failed\n", __location__);
7684                 return False;
7685         }
7686
7687         if (strcmp(val, "bar") != 0) {
7688                 d_printf("%s: gencache_get() returned %s, expected %s\n",
7689                          __location__, val, "bar");
7690                 SAFE_FREE(val);
7691                 return False;
7692         }
7693
7694         SAFE_FREE(val);
7695
7696         if (!gencache_del("foo")) {
7697                 d_printf("%s: gencache_del() failed\n", __location__);
7698                 return False;
7699         }
7700         if (gencache_del("foo")) {
7701                 d_printf("%s: second gencache_del() succeeded\n",
7702                          __location__);
7703                 return False;
7704         }
7705
7706         if (gencache_get("foo", &val, &tm)) {
7707                 d_printf("%s: gencache_get() on deleted entry "
7708                          "succeeded\n", __location__);
7709                 return False;
7710         }
7711
7712         blob = data_blob_string_const_null("bar");
7713         tm = time(NULL) + 60;
7714
7715         if (!gencache_set_data_blob("foo", &blob, tm)) {
7716                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
7717                 return False;
7718         }
7719
7720         if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7721                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
7722                 return False;
7723         }
7724
7725         if (strcmp((const char *)blob.data, "bar") != 0) {
7726                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
7727                          __location__, (const char *)blob.data, "bar");
7728                 data_blob_free(&blob);
7729                 return False;
7730         }
7731
7732         data_blob_free(&blob);
7733
7734         if (!gencache_del("foo")) {
7735                 d_printf("%s: gencache_del() failed\n", __location__);
7736                 return False;
7737         }
7738         if (gencache_del("foo")) {
7739                 d_printf("%s: second gencache_del() succeeded\n",
7740                          __location__);
7741                 return False;
7742         }
7743
7744         if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7745                 d_printf("%s: gencache_get_data_blob() on deleted entry "
7746                          "succeeded\n", __location__);
7747                 return False;
7748         }
7749
7750         return True;
7751 }
7752
7753 static bool rbt_testval(struct db_context *db, const char *key,
7754                         const char *value)
7755 {
7756         struct db_record *rec;
7757         TDB_DATA data = string_tdb_data(value);
7758         bool ret = false;
7759         NTSTATUS status;
7760         TDB_DATA dbvalue;
7761
7762         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
7763         if (rec == NULL) {
7764                 d_fprintf(stderr, "fetch_locked failed\n");
7765                 goto done;
7766         }
7767         status = dbwrap_record_store(rec, data, 0);
7768         if (!NT_STATUS_IS_OK(status)) {
7769                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
7770                 goto done;
7771         }
7772         TALLOC_FREE(rec);
7773
7774         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
7775         if (rec == NULL) {
7776                 d_fprintf(stderr, "second fetch_locked failed\n");
7777                 goto done;
7778         }
7779
7780         dbvalue = dbwrap_record_get_value(rec);
7781         if ((dbvalue.dsize != data.dsize)
7782             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
7783                 d_fprintf(stderr, "Got wrong data back\n");
7784                 goto done;
7785         }
7786
7787         ret = true;
7788  done:
7789         TALLOC_FREE(rec);
7790         return ret;
7791 }
7792
7793 static bool run_local_rbtree(int dummy)
7794 {
7795         struct db_context *db;
7796         bool ret = false;
7797         int i;
7798
7799         db = db_open_rbt(NULL);
7800
7801         if (db == NULL) {
7802                 d_fprintf(stderr, "db_open_rbt failed\n");
7803                 return false;
7804         }
7805
7806         for (i=0; i<1000; i++) {
7807                 char *key, *value;
7808
7809                 if (asprintf(&key, "key%ld", random()) == -1) {
7810                         goto done;
7811                 }
7812                 if (asprintf(&value, "value%ld", random()) == -1) {
7813                         SAFE_FREE(key);
7814                         goto done;
7815                 }
7816
7817                 if (!rbt_testval(db, key, value)) {
7818                         SAFE_FREE(key);
7819                         SAFE_FREE(value);
7820                         goto done;
7821                 }
7822
7823                 SAFE_FREE(value);
7824                 if (asprintf(&value, "value%ld", random()) == -1) {
7825                         SAFE_FREE(key);
7826                         goto done;
7827                 }
7828
7829                 if (!rbt_testval(db, key, value)) {
7830                         SAFE_FREE(key);
7831                         SAFE_FREE(value);
7832                         goto done;
7833                 }
7834
7835                 SAFE_FREE(key);
7836                 SAFE_FREE(value);
7837         }
7838
7839         ret = true;
7840
7841  done:
7842         TALLOC_FREE(db);
7843         return ret;
7844 }
7845
7846
7847 /*
7848   local test for character set functions
7849
7850   This is a very simple test for the functionality in convert_string_error()
7851  */
7852 static bool run_local_convert_string(int dummy)
7853 {
7854         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
7855         const char *test_strings[2] = { "March", "M\303\244rz" };
7856         char dst[7];
7857         int i;
7858
7859         for (i=0; i<2; i++) {
7860                 const char *str = test_strings[i];
7861                 int len = strlen(str);
7862                 size_t converted_size;
7863                 bool ret;
7864
7865                 memset(dst, 'X', sizeof(dst));
7866
7867                 /* first try with real source length */
7868                 ret = convert_string_error(CH_UNIX, CH_UTF8,
7869                                            str, len,
7870                                            dst, sizeof(dst),
7871                                            &converted_size);
7872                 if (ret != true) {
7873                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7874                         goto failed;
7875                 }
7876
7877                 if (converted_size != len) {
7878                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7879                                   str, len, (int)converted_size);
7880                         goto failed;
7881                 }
7882
7883                 if (strncmp(str, dst, converted_size) != 0) {
7884                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7885                         goto failed;
7886                 }
7887
7888                 if (strlen(str) != converted_size) {
7889                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7890                                   (int)strlen(str), (int)converted_size);
7891                         goto failed;
7892                 }
7893
7894                 if (dst[converted_size] != 'X') {
7895                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7896                         goto failed;
7897                 }
7898
7899                 /* now with srclen==-1, this causes the nul to be
7900                  * converted too */
7901                 ret = convert_string_error(CH_UNIX, CH_UTF8,
7902                                            str, -1,
7903                                            dst, sizeof(dst),
7904                                            &converted_size);
7905                 if (ret != true) {
7906                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7907                         goto failed;
7908                 }
7909
7910                 if (converted_size != len+1) {
7911                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7912                                   str, len, (int)converted_size);
7913                         goto failed;
7914                 }
7915
7916                 if (strncmp(str, dst, converted_size) != 0) {
7917                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7918                         goto failed;
7919                 }
7920
7921                 if (len+1 != converted_size) {
7922                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7923                                   len+1, (int)converted_size);
7924                         goto failed;
7925                 }
7926
7927                 if (dst[converted_size] != 'X') {
7928                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7929                         goto failed;
7930                 }
7931
7932         }
7933
7934
7935         TALLOC_FREE(tmp_ctx);
7936         return true;
7937 failed:
7938         TALLOC_FREE(tmp_ctx);
7939         return false;
7940 }
7941
7942
7943 struct talloc_dict_test {
7944         int content;
7945 };
7946
7947 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
7948 {
7949         int *count = (int *)priv;
7950         *count += 1;
7951         return 0;
7952 }
7953
7954 static bool run_local_talloc_dict(int dummy)
7955 {
7956         struct talloc_dict *dict;
7957         struct talloc_dict_test *t;
7958         int key, count, res;
7959         bool ok;
7960
7961         dict = talloc_dict_init(talloc_tos());
7962         if (dict == NULL) {
7963                 return false;
7964         }
7965
7966         t = talloc(talloc_tos(), struct talloc_dict_test);
7967         if (t == NULL) {
7968                 return false;
7969         }
7970
7971         key = 1;
7972         t->content = 1;
7973         ok = talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), &t);
7974         if (!ok) {
7975                 return false;
7976         }
7977
7978         count = 0;
7979         res = talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count);
7980         if (res == -1) {
7981                 return false;
7982         }
7983
7984         if (count != 1) {
7985                 return false;
7986         }
7987
7988         if (count != res) {
7989                 return false;
7990         }
7991
7992         TALLOC_FREE(dict);
7993
7994         return true;
7995 }
7996
7997 static bool run_local_string_to_sid(int dummy) {
7998         struct dom_sid sid;
7999
8000         if (string_to_sid(&sid, "S--1-5-32-545")) {
8001                 printf("allowing S--1-5-32-545\n");
8002                 return false;
8003         }
8004         if (string_to_sid(&sid, "S-1-5-32-+545")) {
8005                 printf("allowing S-1-5-32-+545\n");
8006                 return false;
8007         }
8008         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")) {
8009                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
8010                 return false;
8011         }
8012         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
8013                 printf("allowing S-1-5-32-545-abc\n");
8014                 return false;
8015         }
8016         if (!string_to_sid(&sid, "S-1-5-32-545")) {
8017                 printf("could not parse S-1-5-32-545\n");
8018                 return false;
8019         }
8020         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
8021                 printf("mis-parsed S-1-5-32-545 as %s\n",
8022                        sid_string_tos(&sid));
8023                 return false;
8024         }
8025         return true;
8026 }
8027
8028 static bool run_local_binary_to_sid(int dummy) {
8029         struct dom_sid *sid = talloc(NULL, struct dom_sid);
8030         static const char good_binary_sid[] = {
8031                 0x1, /* revision number */
8032                 15, /* num auths */
8033                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8034                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8035                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8036                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8037                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8038                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8039                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8040                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8041                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8042                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8043                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8044                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8045                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8046                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8047                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8048                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8049         };
8050
8051         static const char long_binary_sid[] = {
8052                 0x1, /* revision number */
8053                 15, /* num auths */
8054                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8055                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8056                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8057                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8058                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8059                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8060                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8061                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8062                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8063                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8064                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8065                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8066                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8067                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8068                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8069                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8070                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8071                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8072                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8073         };
8074
8075         static const char long_binary_sid2[] = {
8076                 0x1, /* revision number */
8077                 32, /* num auths */
8078                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8079                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8080                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8081                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8082                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8083                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8084                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8085                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8086                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8087                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8088                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8089                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8090                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8091                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8092                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8093                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8094                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8095                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8096                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8097                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
8098                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
8099                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
8100                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
8101                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
8102                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
8103                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
8104                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
8105                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
8106                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
8107                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
8108                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
8109                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
8110                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
8111         };
8112
8113         if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
8114                 return false;
8115         }
8116         if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
8117                 return false;
8118         }
8119         if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
8120                 return false;
8121         }
8122         return true;
8123 }
8124
8125 /* Split a path name into filename and stream name components. Canonicalise
8126  * such that an implicit $DATA token is always explicit.
8127  *
8128  * The "specification" of this function can be found in the
8129  * run_local_stream_name() function in torture.c, I've tried those
8130  * combinations against a W2k3 server.
8131  */
8132
8133 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
8134                                        char **pbase, char **pstream)
8135 {
8136         char *base = NULL;
8137         char *stream = NULL;
8138         char *sname; /* stream name */
8139         const char *stype; /* stream type */
8140
8141         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
8142
8143         sname = strchr_m(fname, ':');
8144
8145         if (lp_posix_pathnames() || (sname == NULL)) {
8146                 if (pbase != NULL) {
8147                         base = talloc_strdup(mem_ctx, fname);
8148                         NT_STATUS_HAVE_NO_MEMORY(base);
8149                 }
8150                 goto done;
8151         }
8152
8153         if (pbase != NULL) {
8154                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
8155                 NT_STATUS_HAVE_NO_MEMORY(base);
8156         }
8157
8158         sname += 1;
8159
8160         stype = strchr_m(sname, ':');
8161
8162         if (stype == NULL) {
8163                 sname = talloc_strdup(mem_ctx, sname);
8164                 stype = "$DATA";
8165         }
8166         else {
8167                 if (strcasecmp_m(stype, ":$DATA") != 0) {
8168                         /*
8169                          * If there is an explicit stream type, so far we only
8170                          * allow $DATA. Is there anything else allowed? -- vl
8171                          */
8172                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
8173                         TALLOC_FREE(base);
8174                         return NT_STATUS_OBJECT_NAME_INVALID;
8175                 }
8176                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
8177                 stype += 1;
8178         }
8179
8180         if (sname == NULL) {
8181                 TALLOC_FREE(base);
8182                 return NT_STATUS_NO_MEMORY;
8183         }
8184
8185         if (sname[0] == '\0') {
8186                 /*
8187                  * no stream name, so no stream
8188                  */
8189                 goto done;
8190         }
8191
8192         if (pstream != NULL) {
8193                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
8194                 if (stream == NULL) {
8195                         TALLOC_FREE(sname);
8196                         TALLOC_FREE(base);
8197                         return NT_STATUS_NO_MEMORY;
8198                 }
8199                 /*
8200                  * upper-case the type field
8201                  */
8202                 strupper_m(strchr_m(stream, ':')+1);
8203         }
8204
8205  done:
8206         if (pbase != NULL) {
8207                 *pbase = base;
8208         }
8209         if (pstream != NULL) {
8210                 *pstream = stream;
8211         }
8212         return NT_STATUS_OK;
8213 }
8214
8215 static bool test_stream_name(const char *fname, const char *expected_base,
8216                              const char *expected_stream,
8217                              NTSTATUS expected_status)
8218 {
8219         NTSTATUS status;
8220         char *base = NULL;
8221         char *stream = NULL;
8222
8223         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
8224         if (!NT_STATUS_EQUAL(status, expected_status)) {
8225                 goto error;
8226         }
8227
8228         if (!NT_STATUS_IS_OK(status)) {
8229                 return true;
8230         }
8231
8232         if (base == NULL) goto error;
8233
8234         if (strcmp(expected_base, base) != 0) goto error;
8235
8236         if ((expected_stream != NULL) && (stream == NULL)) goto error;
8237         if ((expected_stream == NULL) && (stream != NULL)) goto error;
8238
8239         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
8240                 goto error;
8241
8242         TALLOC_FREE(base);
8243         TALLOC_FREE(stream);
8244         return true;
8245
8246  error:
8247         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
8248                   fname, expected_base ? expected_base : "<NULL>",
8249                   expected_stream ? expected_stream : "<NULL>",
8250                   nt_errstr(expected_status));
8251         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
8252                   base ? base : "<NULL>", stream ? stream : "<NULL>",
8253                   nt_errstr(status));
8254         TALLOC_FREE(base);
8255         TALLOC_FREE(stream);
8256         return false;
8257 }
8258
8259 static bool run_local_stream_name(int dummy)
8260 {
8261         bool ret = true;
8262
8263         ret &= test_stream_name(
8264                 "bla", "bla", NULL, NT_STATUS_OK);
8265         ret &= test_stream_name(
8266                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
8267         ret &= test_stream_name(
8268                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8269         ret &= test_stream_name(
8270                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
8271         ret &= test_stream_name(
8272                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8273         ret &= test_stream_name(
8274                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
8275         ret &= test_stream_name(
8276                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
8277         ret &= test_stream_name(
8278                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
8279
8280         return ret;
8281 }
8282
8283 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
8284 {
8285         if (a.length != b.length) {
8286                 printf("a.length=%d != b.length=%d\n",
8287                        (int)a.length, (int)b.length);
8288                 return false;
8289         }
8290         if (memcmp(a.data, b.data, a.length) != 0) {
8291                 printf("a.data and b.data differ\n");
8292                 return false;
8293         }
8294         return true;
8295 }
8296
8297 static bool run_local_memcache(int dummy)
8298 {
8299         struct memcache *cache;
8300         DATA_BLOB k1, k2;
8301         DATA_BLOB d1, d2, d3;
8302         DATA_BLOB v1, v2, v3;
8303
8304         TALLOC_CTX *mem_ctx;
8305         char *str1, *str2;
8306         size_t size1, size2;
8307         bool ret = false;
8308
8309         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
8310
8311         if (cache == NULL) {
8312                 printf("memcache_init failed\n");
8313                 return false;
8314         }
8315
8316         d1 = data_blob_const("d1", 2);
8317         d2 = data_blob_const("d2", 2);
8318         d3 = data_blob_const("d3", 2);
8319
8320         k1 = data_blob_const("d1", 2);
8321         k2 = data_blob_const("d2", 2);
8322
8323         memcache_add(cache, STAT_CACHE, k1, d1);
8324         memcache_add(cache, GETWD_CACHE, k2, d2);
8325
8326         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
8327                 printf("could not find k1\n");
8328                 return false;
8329         }
8330         if (!data_blob_equal(d1, v1)) {
8331                 return false;
8332         }
8333
8334         if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8335                 printf("could not find k2\n");
8336                 return false;
8337         }
8338         if (!data_blob_equal(d2, v2)) {
8339                 return false;
8340         }
8341
8342         memcache_add(cache, STAT_CACHE, k1, d3);
8343
8344         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
8345                 printf("could not find replaced k1\n");
8346                 return false;
8347         }
8348         if (!data_blob_equal(d3, v3)) {
8349                 return false;
8350         }
8351
8352         memcache_add(cache, GETWD_CACHE, k1, d1);
8353
8354         if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8355                 printf("Did find k2, should have been purged\n");
8356                 return false;
8357         }
8358
8359         TALLOC_FREE(cache);
8360
8361         cache = memcache_init(NULL, 0);
8362
8363         mem_ctx = talloc_init("foo");
8364
8365         str1 = talloc_strdup(mem_ctx, "string1");
8366         str2 = talloc_strdup(mem_ctx, "string2");
8367
8368         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8369                             data_blob_string_const("torture"), &str1);
8370         size1 = talloc_total_size(cache);
8371
8372         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8373                             data_blob_string_const("torture"), &str2);
8374         size2 = talloc_total_size(cache);
8375
8376         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
8377
8378         if (size2 > size1) {
8379                 printf("memcache leaks memory!\n");
8380                 goto fail;
8381         }
8382
8383         ret = true;
8384  fail:
8385         TALLOC_FREE(cache);
8386         return ret;
8387 }
8388
8389 static void wbclient_done(struct tevent_req *req)
8390 {
8391         wbcErr wbc_err;
8392         struct winbindd_response *wb_resp;
8393         int *i = (int *)tevent_req_callback_data_void(req);
8394
8395         wbc_err = wb_trans_recv(req, req, &wb_resp);
8396         TALLOC_FREE(req);
8397         *i += 1;
8398         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
8399 }
8400
8401 static bool run_local_wbclient(int dummy)
8402 {
8403         struct event_context *ev;
8404         struct wb_context **wb_ctx;
8405         struct winbindd_request wb_req;
8406         bool result = false;
8407         int i, j;
8408
8409         BlockSignals(True, SIGPIPE);
8410
8411         ev = tevent_context_init_byname(talloc_tos(), "epoll");
8412         if (ev == NULL) {
8413                 goto fail;
8414         }
8415
8416         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
8417         if (wb_ctx == NULL) {
8418                 goto fail;
8419         }
8420
8421         ZERO_STRUCT(wb_req);
8422         wb_req.cmd = WINBINDD_PING;
8423
8424         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
8425
8426         for (i=0; i<torture_nprocs; i++) {
8427                 wb_ctx[i] = wb_context_init(ev, NULL);
8428                 if (wb_ctx[i] == NULL) {
8429                         goto fail;
8430                 }
8431                 for (j=0; j<torture_numops; j++) {
8432                         struct tevent_req *req;
8433                         req = wb_trans_send(ev, ev, wb_ctx[i],
8434                                             (j % 2) == 0, &wb_req);
8435                         if (req == NULL) {
8436                                 goto fail;
8437                         }
8438                         tevent_req_set_callback(req, wbclient_done, &i);
8439                 }
8440         }
8441
8442         i = 0;
8443
8444         while (i < torture_nprocs * torture_numops) {
8445                 tevent_loop_once(ev);
8446         }
8447
8448         result = true;
8449  fail:
8450         TALLOC_FREE(ev);
8451         return result;
8452 }
8453
8454 static void getaddrinfo_finished(struct tevent_req *req)
8455 {
8456         char *name = (char *)tevent_req_callback_data_void(req);
8457         struct addrinfo *ainfo;
8458         int res;
8459
8460         res = getaddrinfo_recv(req, &ainfo);
8461         if (res != 0) {
8462                 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
8463                 return;
8464         }
8465         d_printf("gai(%s) succeeded\n", name);
8466         freeaddrinfo(ainfo);
8467 }
8468
8469 static bool run_getaddrinfo_send(int dummy)
8470 {
8471         TALLOC_CTX *frame = talloc_stackframe();
8472         struct fncall_context *ctx;
8473         struct tevent_context *ev;
8474         bool result = false;
8475         const char *names[4] = { "www.samba.org", "notfound.samba.org",
8476                                  "www.slashdot.org", "heise.de" };
8477         struct tevent_req *reqs[4];
8478         int i;
8479
8480         ev = event_context_init(frame);
8481         if (ev == NULL) {
8482                 goto fail;
8483         }
8484
8485         ctx = fncall_context_init(frame, 4);
8486
8487         for (i=0; i<ARRAY_SIZE(names); i++) {
8488                 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
8489                                            NULL);
8490                 if (reqs[i] == NULL) {
8491                         goto fail;
8492                 }
8493                 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
8494                                         discard_const_p(void, names[i]));
8495         }
8496
8497         for (i=0; i<ARRAY_SIZE(reqs); i++) {
8498                 tevent_loop_once(ev);
8499         }
8500
8501         result = true;
8502 fail:
8503         TALLOC_FREE(frame);
8504         return result;
8505 }
8506
8507 static bool dbtrans_inc(struct db_context *db)
8508 {
8509         struct db_record *rec;
8510         uint32_t val;
8511         bool ret = false;
8512         NTSTATUS status;
8513         TDB_DATA value;
8514
8515         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
8516         if (rec == NULL) {
8517                 printf(__location__ "fetch_lock failed\n");
8518                 return false;
8519         }
8520
8521         value = dbwrap_record_get_value(rec);
8522
8523         if (value.dsize != sizeof(uint32_t)) {
8524                 printf(__location__ "value.dsize = %d\n",
8525                        (int)value.dsize);
8526                 goto fail;
8527         }
8528
8529         memcpy(&val, value.dptr, sizeof(val));
8530         val += 1;
8531
8532         status = dbwrap_record_store(
8533                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
8534         if (!NT_STATUS_IS_OK(status)) {
8535                 printf(__location__ "store failed: %s\n",
8536                        nt_errstr(status));
8537                 goto fail;
8538         }
8539
8540         ret = true;
8541 fail:
8542         TALLOC_FREE(rec);
8543         return ret;
8544 }
8545
8546 static bool run_local_dbtrans(int dummy)
8547 {
8548         struct db_context *db;
8549         struct db_record *rec;
8550         NTSTATUS status;
8551         uint32_t initial;
8552         int res;
8553         TDB_DATA value;
8554
8555         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
8556                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1);
8557         if (db == NULL) {
8558                 printf("Could not open transtest.db\n");
8559                 return false;
8560         }
8561
8562         res = dbwrap_transaction_start(db);
8563         if (res != 0) {
8564                 printf(__location__ "transaction_start failed\n");
8565                 return false;
8566         }
8567
8568         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
8569         if (rec == NULL) {
8570                 printf(__location__ "fetch_lock failed\n");
8571                 return false;
8572         }
8573
8574         value = dbwrap_record_get_value(rec);
8575
8576         if (value.dptr == NULL) {
8577                 initial = 0;
8578                 status = dbwrap_record_store(
8579                         rec, make_tdb_data((uint8_t *)&initial,
8580                                            sizeof(initial)),
8581                         0);
8582                 if (!NT_STATUS_IS_OK(status)) {
8583                         printf(__location__ "store returned %s\n",
8584                                nt_errstr(status));
8585                         return false;
8586                 }
8587         }
8588
8589         TALLOC_FREE(rec);
8590
8591         res = dbwrap_transaction_commit(db);
8592         if (res != 0) {
8593                 printf(__location__ "transaction_commit failed\n");
8594                 return false;
8595         }
8596
8597         while (true) {
8598                 uint32_t val, val2;
8599                 int i;
8600
8601                 res = dbwrap_transaction_start(db);
8602                 if (res != 0) {
8603                         printf(__location__ "transaction_start failed\n");
8604                         break;
8605                 }
8606
8607                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
8608                 if (!NT_STATUS_IS_OK(status)) {
8609                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
8610                                nt_errstr(status));
8611                         break;
8612                 }
8613
8614                 for (i=0; i<10; i++) {
8615                         if (!dbtrans_inc(db)) {
8616                                 return false;
8617                         }
8618                 }
8619
8620                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
8621                 if (!NT_STATUS_IS_OK(status)) {
8622                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
8623                                nt_errstr(status));
8624                         break;
8625                 }
8626
8627                 if (val2 != val + 10) {
8628                         printf(__location__ "val=%d, val2=%d\n",
8629                                (int)val, (int)val2);
8630                         break;
8631                 }
8632
8633                 printf("val2=%d\r", val2);
8634
8635                 res = dbwrap_transaction_commit(db);
8636                 if (res != 0) {
8637                         printf(__location__ "transaction_commit failed\n");
8638                         break;
8639                 }
8640         }
8641
8642         TALLOC_FREE(db);
8643         return true;
8644 }
8645
8646 /*
8647  * Just a dummy test to be run under a debugger. There's no real way
8648  * to inspect the tevent_select specific function from outside of
8649  * tevent_select.c.
8650  */
8651
8652 static bool run_local_tevent_select(int dummy)
8653 {
8654         struct tevent_context *ev;
8655         struct tevent_fd *fd1, *fd2;
8656         bool result = false;
8657
8658         ev = tevent_context_init_byname(NULL, "select");
8659         if (ev == NULL) {
8660                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
8661                 goto fail;
8662         }
8663
8664         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
8665         if (fd1 == NULL) {
8666                 d_fprintf(stderr, "tevent_add_fd failed\n");
8667                 goto fail;
8668         }
8669         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
8670         if (fd2 == NULL) {
8671                 d_fprintf(stderr, "tevent_add_fd failed\n");
8672                 goto fail;
8673         }
8674         TALLOC_FREE(fd2);
8675
8676         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
8677         if (fd2 == NULL) {
8678                 d_fprintf(stderr, "tevent_add_fd failed\n");
8679                 goto fail;
8680         }
8681
8682         result = true;
8683 fail:
8684         TALLOC_FREE(ev);
8685         return result;
8686 }
8687
8688 static bool run_local_hex_encode_buf(int dummy)
8689 {
8690         char buf[17];
8691         uint8_t src[8];
8692         int i;
8693
8694         for (i=0; i<sizeof(src); i++) {
8695                 src[i] = i;
8696         }
8697         hex_encode_buf(buf, src, sizeof(src));
8698         if (strcmp(buf, "0001020304050607") != 0) {
8699                 return false;
8700         }
8701         hex_encode_buf(buf, NULL, 0);
8702         if (buf[0] != '\0') {
8703                 return false;
8704         }
8705         return true;
8706 }
8707
8708 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
8709         "0.0.0.0",
8710         "::0",
8711         "1.2.3.1",
8712         "0.0.0.0",
8713         "0.0.0.0",
8714         "1.2.3.2",
8715         "1.2.3.3",
8716         "1.2.3.4",
8717         "1.2.3.5",
8718         "::0",
8719         "1.2.3.6",
8720         "1.2.3.7",
8721         "::0",
8722         "::0",
8723         "::0",
8724         "1.2.3.8",
8725         "1.2.3.9",
8726         "1.2.3.10",
8727         "1.2.3.11",
8728         "1.2.3.12",
8729         "1.2.3.13",
8730         "1001:1111:1111:1000:0:1111:1111:1111",
8731         "1.2.3.1",
8732         "1.2.3.2",
8733         "1.2.3.3",
8734         "1.2.3.12",
8735         "::0",
8736         "::0"
8737 };
8738
8739 static const char *remove_duplicate_addrs2_test_strings_result[] = {
8740         "1.2.3.1",
8741         "1.2.3.2",
8742         "1.2.3.3",
8743         "1.2.3.4",
8744         "1.2.3.5",
8745         "1.2.3.6",
8746         "1.2.3.7",
8747         "1.2.3.8",
8748         "1.2.3.9",
8749         "1.2.3.10",
8750         "1.2.3.11",
8751         "1.2.3.12",
8752         "1.2.3.13",
8753         "1001:1111:1111:1000:0:1111:1111:1111"
8754 };
8755
8756 static bool run_local_remove_duplicate_addrs2(int dummy)
8757 {
8758         struct ip_service test_vector[28];
8759         int count, i;
8760
8761         /* Construct the sockaddr_storage test vector. */
8762         for (i = 0; i < 28; i++) {
8763                 struct addrinfo hints;
8764                 struct addrinfo *res = NULL;
8765                 int ret;
8766
8767                 memset(&hints, '\0', sizeof(hints));
8768                 hints.ai_flags = AI_NUMERICHOST;
8769                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
8770                                 NULL,
8771                                 &hints,
8772                                 &res);
8773                 if (ret) {
8774                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
8775                                 remove_duplicate_addrs2_test_strings_vector[i]);
8776                         return false;
8777                 }
8778                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
8779                 memcpy(&test_vector[i].ss,
8780                         res->ai_addr,
8781                         res->ai_addrlen);
8782                 freeaddrinfo(res);
8783         }
8784
8785         count = remove_duplicate_addrs2(test_vector, i);
8786
8787         if (count != 14) {
8788                 fprintf(stderr, "count wrong (%d) should be 14\n",
8789                         count);
8790                 return false;
8791         }
8792
8793         for (i = 0; i < count; i++) {
8794                 char addr[INET6_ADDRSTRLEN];
8795
8796                 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
8797
8798                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
8799                         fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
8800                                 i,
8801                                 addr,
8802                                 remove_duplicate_addrs2_test_strings_result[i]);
8803                         return false;
8804                 }
8805         }
8806
8807         printf("run_local_remove_duplicate_addrs2: success\n");
8808         return true;
8809 }
8810
8811 static double create_procs(bool (*fn)(int), bool *result)
8812 {
8813         int i, status;
8814         volatile pid_t *child_status;
8815         volatile bool *child_status_out;
8816         int synccount;
8817         int tries = 8;
8818         struct timeval start;
8819
8820         synccount = 0;
8821
8822         child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
8823         if (!child_status) {
8824                 printf("Failed to setup shared memory\n");
8825                 return -1;
8826         }
8827
8828         child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
8829         if (!child_status_out) {
8830                 printf("Failed to setup result status shared memory\n");
8831                 return -1;
8832         }
8833
8834         for (i = 0; i < torture_nprocs; i++) {
8835                 child_status[i] = 0;
8836                 child_status_out[i] = True;
8837         }
8838
8839         start = timeval_current();
8840
8841         for (i=0;i<torture_nprocs;i++) {
8842                 procnum = i;
8843                 if (fork() == 0) {
8844                         pid_t mypid = getpid();
8845                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
8846
8847                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
8848
8849                         while (1) {
8850                                 if (torture_open_connection(&current_cli, i)) break;
8851                                 if (tries-- == 0) {
8852                                         printf("pid %d failed to start\n", (int)getpid());
8853                                         _exit(1);
8854                                 }
8855                                 smb_msleep(10); 
8856                         }
8857
8858                         child_status[i] = getpid();
8859
8860                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
8861
8862                         child_status_out[i] = fn(i);
8863                         _exit(0);
8864                 }
8865         }
8866
8867         do {
8868                 synccount = 0;
8869                 for (i=0;i<torture_nprocs;i++) {
8870                         if (child_status[i]) synccount++;
8871                 }
8872                 if (synccount == torture_nprocs) break;
8873                 smb_msleep(10);
8874         } while (timeval_elapsed(&start) < 30);
8875
8876         if (synccount != torture_nprocs) {
8877                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
8878                 *result = False;
8879                 return timeval_elapsed(&start);
8880         }
8881
8882         /* start the client load */
8883         start = timeval_current();
8884
8885         for (i=0;i<torture_nprocs;i++) {
8886                 child_status[i] = 0;
8887         }
8888
8889         printf("%d clients started\n", torture_nprocs);
8890
8891         for (i=0;i<torture_nprocs;i++) {
8892                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
8893         }
8894
8895         printf("\n");
8896
8897         for (i=0;i<torture_nprocs;i++) {
8898                 if (!child_status_out[i]) {
8899                         *result = False;
8900                 }
8901         }
8902         return timeval_elapsed(&start);
8903 }
8904
8905 #define FLAG_MULTIPROC 1
8906
8907 static struct {
8908         const char *name;
8909         bool (*fn)(int);
8910         unsigned flags;
8911 } torture_ops[] = {
8912         {"FDPASS", run_fdpasstest, 0},
8913         {"LOCK1",  run_locktest1,  0},
8914         {"LOCK2",  run_locktest2,  0},
8915         {"LOCK3",  run_locktest3,  0},
8916         {"LOCK4",  run_locktest4,  0},
8917         {"LOCK5",  run_locktest5,  0},
8918         {"LOCK6",  run_locktest6,  0},
8919         {"LOCK7",  run_locktest7,  0},
8920         {"LOCK8",  run_locktest8,  0},
8921         {"LOCK9",  run_locktest9,  0},
8922         {"UNLINK", run_unlinktest, 0},
8923         {"BROWSE", run_browsetest, 0},
8924         {"ATTR",   run_attrtest,   0},
8925         {"TRANS2", run_trans2test, 0},
8926         {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
8927         {"TORTURE",run_torture,    FLAG_MULTIPROC},
8928         {"RANDOMIPC", run_randomipc, 0},
8929         {"NEGNOWAIT", run_negprot_nowait, 0},
8930         {"NBENCH",  run_nbench, 0},
8931         {"NBENCH2", run_nbench2, 0},
8932         {"OPLOCK1",  run_oplock1, 0},
8933         {"OPLOCK2",  run_oplock2, 0},
8934         {"OPLOCK4",  run_oplock4, 0},
8935         {"DIR",  run_dirtest, 0},
8936         {"DIR1",  run_dirtest1, 0},
8937         {"DIR-CREATETIME",  run_dir_createtime, 0},
8938         {"DENY1",  torture_denytest1, 0},
8939         {"DENY2",  torture_denytest2, 0},
8940         {"TCON",  run_tcon_test, 0},
8941         {"TCONDEV",  run_tcon_devtype_test, 0},
8942         {"RW1",  run_readwritetest, 0},
8943         {"RW2",  run_readwritemulti, FLAG_MULTIPROC},
8944         {"RW3",  run_readwritelarge, 0},
8945         {"RW-SIGNING",  run_readwritelarge_signtest, 0},
8946         {"OPEN", run_opentest, 0},
8947         {"POSIX", run_simple_posix_open_test, 0},
8948         {"POSIX-APPEND", run_posix_append, 0},
8949         {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
8950         {"ASYNC-ECHO", run_async_echo, 0},
8951         { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
8952         { "SHORTNAME-TEST", run_shortname_test, 0},
8953         { "ADDRCHANGE", run_addrchange, 0},
8954 #if 1
8955         {"OPENATTR", run_openattrtest, 0},
8956 #endif
8957         {"XCOPY", run_xcopy, 0},
8958         {"RENAME", run_rename, 0},
8959         {"DELETE", run_deletetest, 0},
8960         {"DELETE-LN", run_deletetest_ln, 0},
8961         {"PROPERTIES", run_properties, 0},
8962         {"MANGLE", torture_mangle, 0},
8963         {"MANGLE1", run_mangle1, 0},
8964         {"W2K", run_w2ktest, 0},
8965         {"TRANS2SCAN", torture_trans2_scan, 0},
8966         {"NTTRANSSCAN", torture_nttrans_scan, 0},
8967         {"UTABLE", torture_utable, 0},
8968         {"CASETABLE", torture_casetable, 0},
8969         {"ERRMAPEXTRACT", run_error_map_extract, 0},
8970         {"PIPE_NUMBER", run_pipe_number, 0},
8971         {"TCON2",  run_tcon2_test, 0},
8972         {"IOCTL",  torture_ioctl_test, 0},
8973         {"CHKPATH",  torture_chkpath_test, 0},
8974         {"FDSESS", run_fdsesstest, 0},
8975         { "EATEST", run_eatest, 0},
8976         { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
8977         { "CHAIN1", run_chain1, 0},
8978         { "CHAIN2", run_chain2, 0},
8979         { "CHAIN3", run_chain3, 0},
8980         { "WINDOWS-WRITE", run_windows_write, 0},
8981         { "NTTRANS-CREATE", run_nttrans_create, 0},
8982         { "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
8983         { "CLI_ECHO", run_cli_echo, 0},
8984         { "GETADDRINFO", run_getaddrinfo_send, 0},
8985         { "TLDAP", run_tldap },
8986         { "STREAMERROR", run_streamerror },
8987         { "NOTIFY-BENCH", run_notify_bench },
8988         { "NOTIFY-BENCH2", run_notify_bench2 },
8989         { "NOTIFY-BENCH3", run_notify_bench3 },
8990         { "BAD-NBT-SESSION", run_bad_nbt_session },
8991         { "SMB-ANY-CONNECT", run_smb_any_connect },
8992         { "NOTIFY-ONLINE", run_notify_online },
8993         { "SMB2-BASIC", run_smb2_basic },
8994         { "SMB2-NEGPROT", run_smb2_negprot },
8995         { "SMB2-SESSION-RECONNECT", run_smb2_session_reconnect },
8996         { "SMB2-TCON-DEPENDENCE", run_smb2_tcon_dependence },
8997         { "SMB2-MULTI-CHANNEL", run_smb2_multi_channel },
8998         { "SMB2-SESSION-REAUTH", run_smb2_session_reauth },
8999         { "CLEANUP1", run_cleanup1 },
9000         { "CLEANUP2", run_cleanup2 },
9001         { "CLEANUP3", run_cleanup3 },
9002         { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
9003         { "LOCAL-GENCACHE", run_local_gencache, 0},
9004         { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
9005         { "LOCAL-CTDB-CONN", run_ctdb_conn, 0},
9006         { "LOCAL-MSG", run_msg_test, 0},
9007         { "LOCAL-DBWRAP-WATCH1", run_dbwrap_watch1, 0 },
9008         { "LOCAL-BASE64", run_local_base64, 0},
9009         { "LOCAL-RBTREE", run_local_rbtree, 0},
9010         { "LOCAL-MEMCACHE", run_local_memcache, 0},
9011         { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
9012         { "LOCAL-WBCLIENT", run_local_wbclient, 0},
9013         { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
9014         { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
9015         { "LOCAL-DBTRANS", run_local_dbtrans, 0},
9016         { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
9017         { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
9018         { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
9019         { "LOCAL-sprintf_append", run_local_sprintf_append, 0},
9020         { "LOCAL-hex_encode_buf", run_local_hex_encode_buf, 0},
9021         { "LOCAL-IDMAP-TDB-COMMON", run_idmap_tdb_common_test, 0},
9022         { "LOCAL-remove_duplicate_addrs2", run_local_remove_duplicate_addrs2, 0},
9023         {NULL, NULL, 0}};
9024
9025
9026
9027 /****************************************************************************
9028 run a specified test or "ALL"
9029 ****************************************************************************/
9030 static bool run_test(const char *name)
9031 {
9032         bool ret = True;
9033         bool result = True;
9034         bool found = False;
9035         int i;
9036         double t;
9037         if (strequal(name,"ALL")) {
9038                 for (i=0;torture_ops[i].name;i++) {
9039                         run_test(torture_ops[i].name);
9040                 }
9041                 found = True;
9042         }
9043
9044         for (i=0;torture_ops[i].name;i++) {
9045                 fstr_sprintf(randomfname, "\\XX%x", 
9046                          (unsigned)random());
9047
9048                 if (strequal(name, torture_ops[i].name)) {
9049                         found = True;
9050                         printf("Running %s\n", name);
9051                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
9052                                 t = create_procs(torture_ops[i].fn, &result);
9053                                 if (!result) { 
9054                                         ret = False;
9055                                         printf("TEST %s FAILED!\n", name);
9056                                 }
9057                         } else {
9058                                 struct timeval start;
9059                                 start = timeval_current();
9060                                 if (!torture_ops[i].fn(0)) {
9061                                         ret = False;
9062                                         printf("TEST %s FAILED!\n", name);
9063                                 }
9064                                 t = timeval_elapsed(&start);
9065                         }
9066                         printf("%s took %g secs\n\n", name, t);
9067                 }
9068         }
9069
9070         if (!found) {
9071                 printf("Did not find a test named %s\n", name);
9072                 ret = False;
9073         }
9074
9075         return ret;
9076 }
9077
9078
9079 static void usage(void)
9080 {
9081         int i;
9082
9083         printf("WARNING samba4 test suite is much more complete nowadays.\n");
9084         printf("Please use samba4 torture.\n\n");
9085
9086         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
9087
9088         printf("\t-d debuglevel\n");
9089         printf("\t-U user%%pass\n");
9090         printf("\t-k               use kerberos\n");
9091         printf("\t-N numprocs\n");
9092         printf("\t-n my_netbios_name\n");
9093         printf("\t-W workgroup\n");
9094         printf("\t-o num_operations\n");
9095         printf("\t-O socket_options\n");
9096         printf("\t-m maximum protocol\n");
9097         printf("\t-L use oplocks\n");
9098         printf("\t-c CLIENT.TXT   specify client load file for NBENCH\n");
9099         printf("\t-A showall\n");
9100         printf("\t-p port\n");
9101         printf("\t-s seed\n");
9102         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
9103         printf("\t-f filename   filename to test\n");
9104         printf("\n\n");
9105
9106         printf("tests are:");
9107         for (i=0;torture_ops[i].name;i++) {
9108                 printf(" %s", torture_ops[i].name);
9109         }
9110         printf("\n");
9111
9112         printf("default test is ALL\n");
9113
9114         exit(1);
9115 }
9116
9117 /****************************************************************************
9118   main program
9119 ****************************************************************************/
9120  int main(int argc,char *argv[])
9121 {
9122         int opt, i;
9123         char *p;
9124         int gotuser = 0;
9125         int gotpass = 0;
9126         bool correct = True;
9127         TALLOC_CTX *frame = talloc_stackframe();
9128         int seed = time(NULL);
9129
9130 #ifdef HAVE_SETBUFFER
9131         setbuffer(stdout, NULL, 0);
9132 #endif
9133
9134         setup_logging("smbtorture", DEBUG_STDOUT);
9135
9136         load_case_tables();
9137
9138         if (is_default_dyn_CONFIGFILE()) {
9139                 if(getenv("SMB_CONF_PATH")) {
9140                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
9141                 }
9142         }
9143         lp_load_global(get_dyn_CONFIGFILE());
9144         load_interfaces();
9145
9146         if (argc < 2) {
9147                 usage();
9148         }
9149
9150         for(p = argv[1]; *p; p++)
9151           if(*p == '\\')
9152             *p = '/';
9153
9154         if (strncmp(argv[1], "//", 2)) {
9155                 usage();
9156         }
9157
9158         fstrcpy(host, &argv[1][2]);
9159         p = strchr_m(&host[2],'/');
9160         if (!p) {
9161                 usage();
9162         }
9163         *p = 0;
9164         fstrcpy(share, p+1);
9165
9166         fstrcpy(myname, get_myname(talloc_tos()));
9167         if (!*myname) {
9168                 fprintf(stderr, "Failed to get my hostname.\n");
9169                 return 1;
9170         }
9171
9172         if (*username == 0 && getenv("LOGNAME")) {
9173           fstrcpy(username,getenv("LOGNAME"));
9174         }
9175
9176         argc--;
9177         argv++;
9178
9179         fstrcpy(workgroup, lp_workgroup());
9180
9181         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
9182                != EOF) {
9183                 switch (opt) {
9184                 case 'p':
9185                         port_to_use = atoi(optarg);
9186                         break;
9187                 case 's':
9188                         seed = atoi(optarg);
9189                         break;
9190                 case 'W':
9191                         fstrcpy(workgroup,optarg);
9192                         break;
9193                 case 'm':
9194                         max_protocol = interpret_protocol(optarg, max_protocol);
9195                         break;
9196                 case 'N':
9197                         torture_nprocs = atoi(optarg);
9198                         break;
9199                 case 'o':
9200                         torture_numops = atoi(optarg);
9201                         break;
9202                 case 'd':
9203                         lp_set_cmdline("log level", optarg);
9204                         break;
9205                 case 'O':
9206                         sockops = optarg;
9207                         break;
9208                 case 'L':
9209                         use_oplocks = True;
9210                         break;
9211                 case 'l':
9212                         local_path = optarg;
9213                         break;
9214                 case 'A':
9215                         torture_showall = True;
9216                         break;
9217                 case 'n':
9218                         fstrcpy(myname, optarg);
9219                         break;
9220                 case 'c':
9221                         client_txt = optarg;
9222                         break;
9223                 case 'e':
9224                         do_encrypt = true;
9225                         break;
9226                 case 'k':
9227 #ifdef HAVE_KRB5
9228                         use_kerberos = True;
9229 #else
9230                         d_printf("No kerberos support compiled in\n");
9231                         exit(1);
9232 #endif
9233                         break;
9234                 case 'U':
9235                         gotuser = 1;
9236                         fstrcpy(username,optarg);
9237                         p = strchr_m(username,'%');
9238                         if (p) {
9239                                 *p = 0;
9240                                 fstrcpy(password, p+1);
9241                                 gotpass = 1;
9242                         }
9243                         break;
9244                 case 'b':
9245                         fstrcpy(multishare_conn_fname, optarg);
9246                         use_multishare_conn = True;
9247                         break;
9248                 case 'B':
9249                         torture_blocksize = atoi(optarg);
9250                         break;
9251                 case 'f':
9252                         test_filename = SMB_STRDUP(optarg);
9253                         break;
9254                 default:
9255                         printf("Unknown option %c (%d)\n", (char)opt, opt);
9256                         usage();
9257                 }
9258         }
9259
9260         d_printf("using seed %d\n", seed);
9261
9262         srandom(seed);
9263
9264         if(use_kerberos && !gotuser) gotpass = True;
9265
9266         while (!gotpass) {
9267                 p = getpass("Password:");
9268                 if (p) {
9269                         fstrcpy(password, p);
9270                         gotpass = 1;
9271                 }
9272         }
9273
9274         printf("host=%s share=%s user=%s myname=%s\n", 
9275                host, share, username, myname);
9276
9277         if (argc == optind) {
9278                 correct = run_test("ALL");
9279         } else {
9280                 for (i=optind;i<argc;i++) {
9281                         if (!run_test(argv[i])) {
9282                                 correct = False;
9283                         }
9284                 }
9285         }
9286
9287         TALLOC_FREE(frame);
9288
9289         if (correct) {
9290                 return(0);
9291         } else {
9292                 return(1);
9293         }
9294 }