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